1 #ifndef LAS_INFO_HPP_
2 #define LAS_INFO_HPP_
3 
4 #include "cado_config.h"               // for HAVE_HWLOC
5 
6 #include <cstddef>                    // for NULL
7 #include <array>                       // for array
8 #include <condition_variable>          // for condition_variable
9 #include <cstdint>                     // for uint64_t, UINT64_MAX
10 #include <list>                        // for list
11 #include <map>                         // for map
12 #include <mutex>                       // for mutex, lock_guard
13 #include <thread>                      // for thread
14 #include <utility>                     // for forward
15 #include <vector>                      // for vector
16 #include <gmp.h>
17 #include "cado_poly.h"   // cxx_cado_poly
18 #include "ecm/batch.hpp"               // for cofac_list
19 #include "ecm/facul.hpp"                   // for facul_strategies_t
20 #include "fb.hpp"                      // for fb_factorbase, fb_factorbase::...
21 #ifdef HAVE_HWLOC
22 #include "hwloc-aux.h"
23 #endif
24 #include "las-bkmult.hpp"              // for bkmult_specifier, bkmult_speci...
25 #include "las-cofactor.hpp"            // for cofactorization_statistics
26 #include "las-dlog-base.hpp"
27 #include "las-memory.hpp"              // for las_memory_accessor
28 #include "las-parallel.hpp"            // for las_parallel_desc
29 #include "las-sieve-shared-data.hpp"   // for sieve_shared_data, sieve_share...
30 #include "las-siever-config.hpp"       // for siever_config (ptr only), siev...
31 #include "params.h"
32 #include "utils_cxx.hpp" // NonCopyable
33 /* forward decls of j_divisibility_helperand unsieve_data are not
34  * sufficient.
35  */
36 #include "las-unsieve.hpp"      // IWYU pragma: keep
37 #include "lock_guarded_container.hpp"  // for lock_guarded_container
38 struct trialdiv_data; // IWYU pragma: keep
39 
40 /* This one wants to have siever_config defined */
41 #include "las-descent-trees.hpp"
42 
43 // #define HILIGHT_START   "\e[01;31m"
44 // #define HILIGHT_END   "\e[00m"
45 #define HILIGHT_START   ""
46 #define HILIGHT_END   ""
47 
48 
49 /* {{{ las_info
50  *
51  * las_info holds general data, mostly unrelated to what is actually
52  * computed within a sieve. las_info also contains outer data, which
53  * lives outside the choice of one particular way to configure the siever
54  * versus another.
55  */
56 struct las_info : public las_parallel_desc, private NonCopyable {
57     // ----- general operational flags
58     const char * galois; /* a string to indicate which galois to use in las */
59     int suppress_duplicates;
60     int adjust_strategy = 0;
61 
62     /* It's not ``general operational'', but global enough to be here */
63     cxx_cado_poly cpoly;
64     gmp_randstate_t rstate;
65 
66     // ----- default config and adaptive configs
67     siever_config_pool config_pool;
68 
69     private:
70     /* It's slightly unfortunate to have "mutable" here, obviously. The
71      * root cause is the fetching of strategies for cofactoring in
72      * duplicate suppression mode. As the call to relation_is_duplicate
73      * happens really deep in the call chain, we have a const ref to las
74      * at this point, and this is generally a good thing ! So the
75      * get_strategies() method must be const.
76      *
77      * Other cache access calls, on the other hand, are all relatively
78      * shallow and can access a non-const ref to las very close by. So
79      * there is no compelling need to have the mutable keyword here, as
80      * we can afford to call them with the non-const ref (see
81      * nfs_work::prepare_for_new_q and nfs_work_cofac::nfs_work_cofac).
82      */
83 #ifdef HAVE_HWLOC
84     mutable std::map<cxx_hwloc_nodeset, sieve_shared_data> shared_structure_cache;
local_cachelas_info85     sieve_shared_data & local_cache() const {
86         cxx_hwloc_nodeset nn = current_memory_binding();
87         return shared_structure_cache.at(nn);
88     }
89     std::map<cxx_hwloc_nodeset, las_memory_accessor> las_memory_accessor_cache;
90     public:
local_memory_accessorlas_info91     las_memory_accessor & local_memory_accessor() {
92         cxx_hwloc_nodeset nn = current_memory_binding();
93         return las_memory_accessor_cache.at(nn);
94     }
95     private:
96 #else
97     mutable sieve_shared_data shared_structure_private;
98     sieve_shared_data & local_cache() const {
99         return shared_structure_private;
100     }
101     las_memory_accessor las_memory_accessor_private;
102     public:
103     las_memory_accessor & local_memory_accessor() {
104         return las_memory_accessor_private;
105     }
106     private:
107 #endif
108 
109     public:
110     /* These accessors are for everyone to use. */
get_factorbase_slicinglas_info111     fb_factorbase::slicing const * get_factorbase_slicing(int side, fb_factorbase::key_type fbK) {
112         sieve_shared_data::side_data & s(local_cache().sides[side]);
113         return s.get_factorbase_slicing(fbK);
114     }
get_trialdiv_datalas_info115     trialdiv_data const * get_trialdiv_data(int side, fb_factorbase::key_type fbK, fb_factorbase::slicing const * fbs) {
116         return local_cache().sides[side].get_trialdiv_data(fbK, fbs);
117     }
get_unsieve_datalas_info118     unsieve_data const * get_unsieve_data(siever_config const & conf) {
119         return local_cache().get_unsieve_data(conf);
120     }
get_j_divisibility_helperlas_info121     j_divisibility_helper const * get_j_divisibility_helper(int J) {
122         return local_cache().get_j_divisibility_helper(J);
123     }
get_strategieslas_info124     facul_strategies_t const * get_strategies(siever_config const & conf) const {
125         return local_cache().get_strategies(conf);
126     }
no_fblas_info127     bool no_fb(int side) const {
128         return local_cache().sides[side].no_fb();
129     }
130 
131     private:
132     bkmult_specifier bk_multiplier { 1.0 };
133     mutable std::mutex mm;
134 
135     public:
grow_bk_multiplierlas_info136     void grow_bk_multiplier(bkmult_specifier::key_type const& key, double d) {
137         std::lock_guard<std::mutex> foo(mm);
138         bk_multiplier.grow(key, d);
139     }
get_bk_multiplierlas_info140     bkmult_specifier get_bk_multiplier() const {
141         std::lock_guard<std::mutex> foo(mm);
142         return bk_multiplier;
143     }
144 
145     /* For composite special-q: note present both in las_info and
146      * las_todo_list */
147     bool allow_composite_q = false;
148     uint64_t qfac_min = 1024;
149     uint64_t qfac_max = UINT64_MAX;
is_in_qfac_rangelas_info150     inline bool is_in_qfac_range(uint64_t p) const {
151         return (p >= qfac_min) && (p <= qfac_max);
152     }
153 
154     std::array<unsigned long, 2> dupqmin;   /* smallest q sieved, for dupsup */
155     std::array<unsigned long, 2> dupqmax;   /* largest q sieved, for dupsup */
156 
157     // ----- stuff roughly related to the descent
158     unsigned int max_hint_bitsize[2];
159     int * hint_lookups[2]; /* quick access indices into hint_table */
160     /* This is an opaque pointer to C++ code. */
161     void * descent_helper;
162     las_dlog_base dlog_base;
163     mutable descent_tree tree;
164     void init_hint_table(param_list_ptr);
165     void clear_hint_table();
166 
167     // ----- special mode when we don't compute relations, but read them
168     // from a relation cache instead.
169 
170     std::string relation_cache;
171     void reproduce_relations_from_cache(las_todo_entry const & doing);
172 
173     // ----- batch mode
174     int batch; /* batch mode for cofactorization */
175 
176     /* the batch_print_survivors holds several variables that are
177      * attached to the process of printing the survivors to files. This
178      * is activated by the batch_print_survivors option, and only if the
179      * batch_print_survivors_filename option is set (otherwise printing
180      * just goes to stdout, period). Printing
181      * is typically handled by one or maybe several print-dedicated
182      * threads. In most normal cases, one printing thread should be
183      * enough. Most fields in here are accessed with mm acquired. cv is
184      * here for printing threads waiting for new work notifications.
185      */
186     struct batch_print_survivors_t {
187         mutable std::mutex mm;
188         mutable std::condition_variable cv;
189         bool done = false;
190         std::list<cofac_list> todo;
191 
192         const char *filename; // basename for the files
193         uint64_t    filesize; // number of survivors per file
194         int         counter;  // current index of filename
195         int number_of_printers;
196         std::vector<std::thread>  printers;     // id of the thread doing writing (if any)
operator boollas_info::batch_print_survivors_t197         operator bool() const { return filename != NULL; }
198 
199         void doit();
200     } batch_print_survivors;
201 
202     const char *batch_file[2];
203     int batchlpb[2];
204     int batchmfb[2];
205 
206     /* Would this rather go somewhere else ? In a global (not per-sq)
207      * version of nfs_work_cofac perhaps ?
208      *
209      * We're really over-using mutable modifiers with this struct. It's
210      * annoying me, and more than a hint at the fact that we should think
211      * the design a bit differently.
212      */
213     mutable lock_guarded_container<cofac_list> L; /* store (a,b) and corresponding cofactors in batch mode */
214 
215     /* ----- cofactorization statistics for the default config */
216     mutable cofactorization_statistics cofac_stats;
217 
218     const char *dump_filename;
219 
220 
221     /* typicall call order is as follows */
222     las_info(cxx_param_list &);
set_parallellas_info223     template<typename... Args> void set_parallel(cxx_param_list &pl, Args&& ...args) {
224         (las_parallel_desc&)*this = las_parallel_desc(pl, std::forward<Args>(args)...);
225         prepare_sieve_shared_data(pl);
226     }
227     void prepare_sieve_shared_data(cxx_param_list & pl);
228     void load_factor_base(cxx_param_list & pl);
229     ~las_info();
230 
231     static void declare_usage(cxx_param_list & pl);
232     static void configure_switches(cxx_param_list & pl);
233     static void configure_aliases(cxx_param_list & pl);
234 };
235 /* }}} */
236 
237 
238 #endif	/* LAS_INFO_HPP_ */
239