@@ -19,9 +19,7 @@ void ThreadPool::loop_until_cancelled(
1919 utility::forwardable_span<const CountryInstance> country_keys,
2020 utility::forwardable_span<const GoodDefinition> good_keys,
2121 utility::forwardable_span<const Strata> strata_keys,
22- utility::forwardable_span<GoodInstance> goods_chunk,
23- utility::forwardable_span<CountryInstance> countries_chunk,
24- utility::forwardable_span<ProvinceInstance> provinces_chunk
22+ utility::forwardable_span<WorkBundle> work_bundles
2523) {
2624 IndexedFlatMap<GoodDefinition, char > reusable_goods_mask { good_keys };
2725 IndexedFlatMap<CountryInstance, fixed_point_t > reusable_country_map_0 { country_keys },
@@ -67,46 +65,58 @@ void ThreadPool::loop_until_cancelled(
6765 case work_t ::NONE:
6866 break ;
6967 case work_t ::GOOD_EXECUTE_ORDERS:
70- for (GoodMarket& good : goods_chunk) {
71- good.execute_orders (
72- reusable_country_map_0,
73- reusable_country_map_1,
74- reusable_vectors_span.first <GoodMarket::VECTORS_FOR_EXECUTE_ORDERS>()
75- );
68+ for (WorkBundle& work_bundle : work_bundles) {
69+ for (GoodMarket& good : work_bundle.goods_chunk ) {
70+ good.execute_orders (
71+ reusable_country_map_0,
72+ reusable_country_map_1,
73+ reusable_vectors_span.first <GoodMarket::VECTORS_FOR_EXECUTE_ORDERS>()
74+ );
75+ }
7676 }
7777 break ;
7878 case work_t ::PROVINCE_TICK:
79- for (ProvinceInstance& province : provinces_chunk) {
80- province.province_tick (
81- current_date,
82- reusable_pop_values,
83- reusable_goods_mask,
84- reusable_vectors_span.first <ProvinceInstance::VECTORS_FOR_PROVINCE_TICK>()
85- );
79+ for (WorkBundle& work_bundle : work_bundles) {
80+ for (ProvinceInstance& province : work_bundle.provinces_chunk ) {
81+ province.province_tick (
82+ current_date,
83+ reusable_pop_values,
84+ work_bundle.random_number_generator ,
85+ reusable_goods_mask,
86+ reusable_vectors_span.first <ProvinceInstance::VECTORS_FOR_PROVINCE_TICK>()
87+ );
88+ }
8689 }
8790 break ;
8891 case work_t ::PROVINCE_INITIALISE_FOR_NEW_GAME:
89- for (ProvinceInstance& province : provinces_chunk) {
90- province.initialise_for_new_game (
91- current_date,
92- reusable_pop_values,
93- reusable_goods_mask,
94- reusable_vectors_span.first <ProvinceInstance::VECTORS_FOR_PROVINCE_TICK>()
95- );
92+ for (WorkBundle& work_bundle : work_bundles) {
93+ for (ProvinceInstance& province : work_bundle.provinces_chunk ) {
94+ province.initialise_for_new_game (
95+ current_date,
96+ reusable_pop_values,
97+ work_bundle.random_number_generator ,
98+ reusable_goods_mask,
99+ reusable_vectors_span.first <ProvinceInstance::VECTORS_FOR_PROVINCE_TICK>()
100+ );
101+ }
96102 }
97103 break ;
98104 case work_t ::COUNTRY_TICK_BEFORE_MAP:
99- for (CountryInstance& country : countries_chunk) {
100- country.country_tick_before_map (
101- reusable_goods_mask,
102- reusable_vectors_span.first <CountryInstance::VECTORS_FOR_COUNTRY_TICK>(),
103- reusable_index_vector
104- );
105+ for (WorkBundle& work_bundle : work_bundles) {
106+ for (CountryInstance& country : work_bundle.countries_chunk ) {
107+ country.country_tick_before_map (
108+ reusable_goods_mask,
109+ reusable_vectors_span.first <CountryInstance::VECTORS_FOR_COUNTRY_TICK>(),
110+ reusable_index_vector
111+ );
112+ }
105113 }
106114 break ;
107115 case work_t ::COUNTRY_TICK_AFTER_MAP:
108- for (CountryInstance& country : countries_chunk) {
109- country.country_tick_after_map (current_date);
116+ for (WorkBundle& work_bundle : work_bundles) {
117+ for (CountryInstance& country : work_bundle.countries_chunk ) {
118+ country.country_tick_after_map (current_date);
119+ }
110120 }
111121 break ;
112122 }
@@ -181,18 +191,17 @@ void ThreadPool::initialise_threadpool(
181191 return ;
182192 }
183193
184- const size_t max_worker_threads = std::max<size_t >(std::thread::hardware_concurrency (), 1 );
185- threads.reserve (max_worker_threads);
186- work_per_thread.resize (max_worker_threads, work_t ::NONE);
194+ RandomU32 master_rng { }; // TODO seed?
187195
188- const auto [goods_quotient, goods_remainder] = std::ldiv (goods.size (), max_worker_threads);
189- const auto [countries_quotient, countries_remainder] = std::ldiv (countries.size (), max_worker_threads);
190- const auto [provinces_quotient, provinces_remainder] = std::ldiv (provinces.size (), max_worker_threads);
196+
197+ const auto [goods_quotient, goods_remainder] = std::ldiv (goods.size (), WORK_BUNDLE_COUNT);
198+ const auto [countries_quotient, countries_remainder] = std::ldiv (countries.size (), WORK_BUNDLE_COUNT);
199+ const auto [provinces_quotient, provinces_remainder] = std::ldiv (provinces.size (), WORK_BUNDLE_COUNT);
191200 auto goods_begin = goods.begin ();
192201 auto countries_begin = countries.begin ();
193202 auto provinces_begin = provinces.begin ();
194203
195- for (size_t i = 0 ; i < max_worker_threads ; i++) {
204+ for (size_t i = 0 ; i < WORK_BUNDLE_COUNT ; i++) {
196205 const size_t goods_chunk_size = i < goods_remainder
197206 ? goods_quotient + 1
198207 : goods_quotient;
@@ -207,6 +216,36 @@ void ThreadPool::initialise_threadpool(
207216 auto countries_end = countries_begin + countries_chunk_size;
208217 auto provinces_end = provinces_begin + provinces_chunk_size;
209218
219+ all_work_bundles[i] = WorkBundle {
220+ master_rng.generator ().serialize (),
221+ std::span<CountryInstance>{ countries_begin, countries_end },
222+ std::span<GoodInstance>{ goods_begin, goods_end },
223+ std::span<ProvinceInstance>{ provinces_begin, provinces_end }
224+ };
225+
226+ // ensure different state for next WorkBundle
227+ master_rng.generator ().jump ();
228+
229+ goods_begin = goods_end;
230+ countries_begin = countries_end;
231+ provinces_begin = provinces_end;
232+ }
233+
234+ const size_t max_worker_threads = std::max<size_t >(std::thread::hardware_concurrency (), 1 );
235+ threads.reserve (max_worker_threads);
236+ work_per_thread.resize (max_worker_threads, work_t ::NONE);
237+
238+
239+ const auto [work_bundles_quotient, work_bundles_remainder] = std::ldiv (WORK_BUNDLE_COUNT, max_worker_threads);
240+ auto work_bundles_begin = all_work_bundles.begin ();
241+
242+ for (size_t i = 0 ; i < max_worker_threads; ++i) {
243+ const size_t work_bundles_chunk_size = i < work_bundles_remainder
244+ ? work_bundles_quotient + 1
245+ : work_bundles_quotient;
246+
247+ auto work_bundles_end = work_bundles_begin + work_bundles_chunk_size;
248+
210249 threads.emplace_back (
211250 [
212251 this ,
@@ -219,9 +258,8 @@ void ThreadPool::initialise_threadpool(
219258 countries,
220259 good_keys,
221260 strata_keys,
222- goods_begin, goods_end,
223- countries_begin, countries_end,
224- provinces_begin, provinces_end
261+ work_bundles_begin,
262+ work_bundles_end
225263 ]() -> void {
226264 loop_until_cancelled (
227265 work_for_thread,
@@ -233,16 +271,12 @@ void ThreadPool::initialise_threadpool(
233271 countries,
234272 good_keys,
235273 strata_keys,
236- std::span<GoodInstance>{ goods_begin, goods_end },
237- std::span<CountryInstance>{ countries_begin, countries_end },
238- std::span<ProvinceInstance>{ provinces_begin, provinces_end }
274+ std::span<WorkBundle>{ work_bundles_begin, work_bundles_end }
239275 );
240276 }
241277 );
242278
243- goods_begin = goods_end;
244- countries_begin = countries_end;
245- provinces_begin = provinces_end;
279+ work_bundles_begin = work_bundles_end;
246280 }
247281}
248282
0 commit comments