1 #include "cado.h" // IWYU pragma: keep
2 
3 #include <climits>           // for ULONG_MAX
4 #include <cmath>             // for log2
5 #include <cstdio>             // for fprintf, NULL, stderr
6 #include <cstdlib>           // for abort, exit, EXIT_FAILURE
7 #include <gmp.h>              // for GMP_LIMB_BITS, gmp_randclear, gmp_randi...
8 #include "ecm/batch.hpp"          // for cofac_list
9 #include "las-info.hpp"
10 #include "las-todo-list.hpp"  // for las_todo_list
11 #include "macros.h"           // for ASSERT_ALWAYS
12 #include "params.h"
13 
14 /* las_info stuff */
15 
configure_aliases(cxx_param_list & pl)16 void las_info::configure_aliases(cxx_param_list & pl)
17 {
18     cxx_cado_poly::configure_aliases(pl);
19 }
20 
configure_switches(cxx_param_list & pl)21 void las_info::configure_switches(cxx_param_list & pl)
22 {
23     cxx_cado_poly::configure_switches(pl);
24     las_todo_list::configure_switches(pl);
25     param_list_configure_switch(pl, "-allow-compsq", NULL);
26     param_list_configure_switch(pl, "-dup", NULL);
27     param_list_configure_switch(pl, "-batch", NULL);
28 }
29 
declare_usage(cxx_param_list & pl)30 void las_info::declare_usage(cxx_param_list & pl)
31 {
32     cxx_cado_poly::declare_usage(pl);
33     siever_config_pool::declare_usage(pl);
34     sieve_shared_data::declare_usage(pl);
35     las_dlog_base::declare_usage(pl);
36     cofactorization_statistics::declare_usage(pl);
37 
38 
39     param_list_decl_usage(pl, "seed", "Use this seed for random state seeding (currently used only by --random-sample)");
40 
41     param_list_decl_usage(pl, "galois", "depending on the specified galois automorphism, sieve only part of the q's");
42 
43     /* Note: also declared by las_todo_list ! */
44     param_list_decl_usage(pl, "allow-compsq", "allows composite special-q");
45     param_list_decl_usage(pl, "qfac-min", "factors of q must be at least that");
46     param_list_decl_usage(pl, "qfac-max", "factors of q must be at most that");
47 
48 
49 
50 
51     param_list_decl_usage(pl, "dup", "suppress duplicate relations");
52     param_list_decl_usage(pl, "dup-qmin", "lower limit of global q-range for 2-sided duplicate removal");
53     param_list_decl_usage(pl, "dup-qmax", "upper limit of global q-range for 2-sided duplicate removal");
54     param_list_decl_usage(pl, "adjust-strategy", "strategy used to adapt the sieving range to the q-lattice basis (0 = logI constant, J so that boundary is capped; 1 = logI constant, (a,b) plane norm capped; 2 = logI dynamic, skewed basis; 3 = combine 2 and then 0) ; default=0");
55 
56 
57     param_list_decl_usage(pl, "batch", "use batch cofactorization");
58     param_list_decl_usage(pl, "batch0", "side-0 batch file");
59     param_list_decl_usage(pl, "batch1", "side-1 batch file");
60     param_list_decl_usage(pl, "batchmfb0", "cofactor bound on side 0 to be considered after batch cofactorization. After primes below 2^batchlpb0 have been extracted, cofactors below this bound will go through ecm. Defaults to lpb0.");
61     param_list_decl_usage(pl, "batchmfb1", "cofactor bound on side 1 to be considered after batch cofactorization. After primes below 2^batchlpb1 have been extracted, cofactors below this bound will go through ecm. Defaults to lpb1.");
62     param_list_decl_usage(pl, "batchlpb0", "large prime bound on side 0 to be considered by batch cofactorization. Primes between lim0 and 2^batchlpb0 will be extracted by product trees. Defaults to lpb0.");
63     param_list_decl_usage(pl, "batchlpb1", "large prime bound on side 1 to be considered by batch cofactorization. Primes between lim1 and 2^batchlpb1 will be extracted by product trees. Defaults to lpb1.");
64     param_list_decl_usage(pl, "batch-print-survivors", "just print survivors to files with the given basename for an external cofactorization");
65     param_list_decl_usage(pl, "batch-print-survivors-filesize", "write that many survivors per file");
66     param_list_decl_usage(pl, "batch-print-survivors-number-of-printers", "use this number of I/O threads to write survivor files. defaults to 1, and should not be changed except in very unusual cases");
67 
68     param_list_decl_usage(pl, "relation_cache", "Directory with cache of collected relation for sampling within a known data set. Useful only with --random-sample\n");
69     param_list_decl_usage(pl, "dumpfile", "Dump entire sieve region to file for debugging.");
70 }
71 
72 
prepare_sieve_shared_data(cxx_param_list & pl)73 void las_info::prepare_sieve_shared_data(cxx_param_list & pl)
74 {
75 #ifdef HAVE_HWLOC
76     shared_structure_cache.clear();
77     set_loose_binding();
78     for(int k = 0 ; k < number_of_subjobs_total() ; k+= number_of_subjobs_per_memory_binding_zone()) {
79         set_subjob_mem_binding(k);
80         /* gcc pre 4.7 does not have map::emplace ; while it's
81          * admittedly not a c++11-complete compiler anyway, we still have
82          * hope to use such an ancient thing on a few machines (old *bsd,
83          * for example).
84          *
85          * See:
86          * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=44436#c30
87          */
88 #if 0
89         shared_structure_cache.emplace(
90                 current_memory_binding(),
91                 sieve_shared_data(cpoly, pl));
92 #else
93         std::pair<cxx_hwloc_nodeset, sieve_shared_data> v(
94                 current_memory_binding(),
95                 sieve_shared_data(cpoly, pl));
96         shared_structure_cache.insert(std::move(v));
97         /* for this one, the default ctor is good enough */
98         las_memory_accessor_cache[current_memory_binding()];
99 #endif
100     }
101     set_loose_binding();
102 #else
103     shared_structure_private = sieve_shared_data(cpoly, pl);
104     /* the default-constructed memory accessor is fine */
105 #endif
106 }
107 
load_factor_base(cxx_param_list & pl)108 void las_info::load_factor_base(cxx_param_list & pl)
109 {
110 #ifdef HAVE_HWLOC
111     set_loose_binding();
112     for(int k = 0 ; k < number_of_subjobs_total() ; k+= number_of_subjobs_per_memory_binding_zone()) {
113         set_subjob_mem_binding(k);
114         /* right, so at this point we would probably need to
115          * compute the factor base just once, and copy it in ram, isn't
116          * it ?
117          */
118         shared_structure_cache.at(current_memory_binding()).load_factor_base(pl, number_of_threads_loose());
119     }
120     set_loose_binding();
121 #else
122     shared_structure_private.load_factor_base(pl, number_of_threads_loose());
123 #endif
124 }
125 
las_info(cxx_param_list & pl)126 las_info::las_info(cxx_param_list & pl)
127     : cpoly(pl),
128       config_pool(pl),
129 #ifdef HAVE_HWLOC
130       shared_structure_cache(),
131 #else
132       shared_structure_private(cpoly, pl),
133 #endif
134       dlog_base(cpoly, pl),
135       cofac_stats(pl)
136       /*{{{*/
137 {
138     /* We strive to initialize things in the exact order they're written
139      * in the struct */
140     // ----- general operational flags {{{
141     gmp_randinit_default(rstate);
142     unsigned long seed = 0;
143     if (param_list_parse_ulong(pl, "seed", &seed))
144         gmp_randseed_ui(rstate, seed);
145 
146     galois = param_list_lookup_string(pl, "galois");
147     suppress_duplicates = param_list_parse_switch(pl, "-dup");
148 
149     if (const char * tmp = param_list_lookup_string(pl, "bkmult")) {
150         bk_multiplier = bkmult_specifier(tmp);
151     }
152 
153     param_list_parse_int(pl, "adjust-strategy", &adjust_strategy);
154 
155     // }}}
156 
157 
158     /* composite special-q ? Note: this block is present both in
159      * las-todo-list.cpp and las-info.cpp */
160     if ((allow_composite_q = param_list_parse_switch(pl, "-allow-compsq"))) {
161         /* defaults are set in the class description */
162         param_list_parse_uint64(pl, "qfac-min", &qfac_min);
163         param_list_parse_uint64(pl, "qfac-max", &qfac_max);
164     }
165 
166     param_list_parse_string(pl, "relation_cache", relation_cache);
167 
168     // ----- stuff roughly related to the descent {{{
169     descent_helper = NULL;
170     // }}}
171 
172     /* {{{ duplicate suppression */
173     dupqmin = {{ 0, 0 }};
174     dupqmax = {{ ULONG_MAX, ULONG_MAX}};
175     if (!param_list_parse_ulong_and_ulong(pl, "dup-qmin", &dupqmin[0], ",") && suppress_duplicates) {
176         fprintf(stderr, "Error: -dup-qmin is mandatory with -dup\n");
177         exit(EXIT_FAILURE);
178     }
179     param_list_parse_ulong_and_ulong(pl, "dup-qmax", &dupqmax[0], ",");
180     /* Change 0 (not initialized) into LONG_MAX */
181     for (auto & x : dupqmin) if (x == 0) x = ULONG_MAX;
182 
183     /* }}} */
184 
185     // ----- batch mode {{{
186     batch = param_list_parse_switch(pl, "-batch");
187 
188     if (batch) {
189         ASSERT_ALWAYS(config_pool.default_config_ptr);
190         siever_config const & sc0(*config_pool.default_config_ptr);
191 	batchlpb[0] = sc0.sides[0].lpb;
192 	batchlpb[1] = sc0.sides[1].lpb;
193 	batchmfb[0] = sc0.sides[0].lpb;
194 	batchmfb[1] = sc0.sides[1].lpb;
195         param_list_parse_int(pl, "batchlpb0", &(batchlpb[0]));
196         param_list_parse_int(pl, "batchlpb1", &(batchlpb[1]));
197         param_list_parse_int(pl, "batchmfb0", &(batchmfb[0]));
198         param_list_parse_int(pl, "batchmfb1", &(batchmfb[1]));
199 	batch_file[0] = param_list_lookup_string (pl, "batch0");
200 	batch_file[1] = param_list_lookup_string (pl, "batch1");
201 
202         for(int side = 0 ; side < 2 ; side++) {
203             // the product of primes up to B takes \log2(B)-\log\log 2 /
204             // \log 2 bits. The added constant is 0.5287.
205             if (batchlpb[side] + 0.5287 >= 31 + log2(GMP_LIMB_BITS)) {
206                 fprintf(stderr, "Gnu MP cannot deal with primes product that large (max 37 bits, asked for batchlpb%d=%d)\n", side, batchlpb[side]);
207                 abort();
208             } else if (batchlpb[side] + 0.5287 >= 34) {
209                 fprintf(stderr, "Gnu MP's mpz_inp_raw and mpz_out_raw functions are limited to integers of at most 34 bits (asked for batchlpb%d=%d)\n",side,batchlpb[side]);
210                 abort();
211             }
212         }
213     }
214 
215 
216     batch_print_survivors.filename = param_list_lookup_string(pl, "batch-print-survivors");
217     if (batch_print_survivors.filename) {
218         batch_print_survivors.counter = 0;
219         batch_print_survivors.number_of_printers = 1;
220         batch_print_survivors.filesize = 1000000;
221         param_list_parse_uint64(pl, "batch-print-survivors-filesize", &batch_print_survivors.filesize);
222         param_list_parse_int(pl, "batch-print-survivors-number-of-printers", &batch_print_survivors.number_of_printers);
223     }
224     // }}}
225 
226     dump_filename = param_list_lookup_string(pl, "dumpfile");
227 }/*}}}*/
228 
229 
~las_info()230 las_info::~las_info()/*{{{*/
231 {
232 
233     // ----- general operational flags {{{
234     gmp_randclear(rstate);
235 
236     // }}}
237 
238 }/*}}}*/
239