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