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