66 using clock = std::chrono::steady_clock;
71 const int i1_raw = 5, i2_raw = 77, j1_raw = 3, j2_raw = 10;
72 const int i1 = (N ? (i1_raw % N) : 0);
73 const int i2 = (N ? (i2_raw % N) : 0);
74 const int j1 = (N ? (j1_raw % N) : 0);
75 const int j2 = (N ? (j2_raw % N) : 0);
77 auto SRC_A = std::make_shared<Block>(); SRC_A->blockname =
"SRC_A"; SRC_A->set_scale(1.0);
78 auto SRC_B = std::make_shared<Block>(); SRC_B->blockname =
"SRC_B"; SRC_B->set_scale(1.0);
79 auto SRC_C = std::make_shared<Block>(); SRC_C->blockname =
"SRC_C"; SRC_C->set_scale(1.0);
81 auto SCALE = std::make_shared<Block>(); SCALE->blockname =
"SCALE"; SCALE->set_scale(1.0);
82 SCALE->store(
LhaID(1), make_param(
"SCALE",
LhaID(1), 1.25));
84 for (
int i = 0; i < N; ++i) {
86 SRC_A->store(
id, make_param(
"SRC_A",
id, 1.0*i));
87 SRC_B->store(
id, make_param(
"SRC_B",
id, 2.0*i));
88 SRC_C->store(
id, make_param(
"SRC_C",
id, 0.5*i));
91 int upd_FUSED_AB = 0, upd_FUSED_BC = 0, upd_SCALED_A = 0, upd_MIXED = 0, upd_REDUCED = 0, upd_META = 0;
92 int upd_DP_AZ_1 = 0, upd_DP_AZ_2 = 0, upd_DP_MS_1 = 0, upd_DP_MS_2 = 0, upd_DP_META = 0;
94 auto FUSED_AB = std::make_shared<DependentBlock>(
95 std::unordered_map<std::string, std::shared_ptr<Block>>{
96 {
"SRC_A", SRC_A}, {
"SRC_B", SRC_B}
98 [&upd_FUSED_AB, N](
const BlockSrc& srcs, std::shared_ptr<DependentBlock> self) {
100 for (
int i = 0; i < N; ++i) {
102 double a = srcs.get_val(
"SRC_A",
id);
103 double b = srcs.get_val(
"SRC_B",
id);
104 double z = a + 2.0*b;
105 if (self->contains(
id)) self->assign(
id, z);
106 else self->store(
id, std::make_shared<Parameter>(
ParamId(self->get_name(),
id), z, 0., 0.));
110 FUSED_AB->blockname =
"FUSED_AB"; FUSED_AB->set_scale(1.0); FUSED_AB->init();
112 auto FUSED_BC = std::make_shared<DependentBlock>(
113 std::unordered_map<std::string, std::shared_ptr<Block>>{
114 {
"SRC_B", SRC_B}, {
"SRC_C", SRC_C}
116 [&upd_FUSED_BC, N](
const BlockSrc& srcs, std::shared_ptr<DependentBlock> self) {
118 for (
int i = 0; i < N; ++i) {
120 double b = srcs.get_val(
"SRC_B",
id);
121 double c = srcs.get_val(
"SRC_C",
id);
123 if (self->contains(
id)) self->assign(
id, y);
124 else self->store(
id, std::make_shared<Parameter>(
ParamId(self->get_name(),
id), y, 0., 0.));
128 FUSED_BC->blockname =
"FUSED_BC"; FUSED_BC->set_scale(1.0); FUSED_BC->init();
130 auto SCALED_A = std::make_shared<DependentBlock>(
131 std::unordered_map<std::string, std::shared_ptr<Block>>{
132 {
"SRC_A", SRC_A}, {
"SCALE", SCALE}
134 [&upd_SCALED_A, N](
const BlockSrc& srcs, std::shared_ptr<DependentBlock> self) {
136 double sf = srcs.get_val(
"SCALE", 1);
137 for (
int i = 0; i < N; ++i) {
139 double a = srcs.get_val(
"SRC_A",
id);
141 if (self->contains(
id)) self->assign(
id, s);
142 else self->store(
id, std::make_shared<Parameter>(
ParamId(self->get_name(),
id), s, 0., 0.));
146 SCALED_A->blockname =
"SCALED_A"; SCALED_A->set_scale(1.0); SCALED_A->init();
148 auto AVG = std::make_shared<DependentBlock>(
149 std::unordered_map<std::string, std::shared_ptr<Block>>{
150 {
"SRC_A", SRC_A}, {
"SRC_B", SRC_B}, {
"SRC_C", SRC_C}
152 [N](
const BlockSrc& srcs, std::shared_ptr<DependentBlock> self) {
153 for (
int i = 0; i < N; ++i) {
155 double a = srcs.get_val(
"SRC_A",
id);
156 double b = srcs.get_val(
"SRC_B",
id);
157 double c = srcs.get_val(
"SRC_C",
id);
158 double avg = (a + b + c) / 3.0;
159 if (self->contains(
id)) self->assign(
id, avg);
160 else self->store(
id, std::make_shared<Parameter>(
ParamId(self->get_name(),
id), avg, 0., 0.));
164 AVG->blockname =
"AVG"; AVG->set_scale(1.0); AVG->init();
166 auto MIXED = std::make_shared<DependentBlock>(
167 std::unordered_map<std::string, std::shared_ptr<Block>>{
168 {
"SRC_A", SRC_A}, {
"FUSED_AB", FUSED_AB}, {
"FUSED_BC", FUSED_BC}, {
"AVG", AVG}
170 [&upd_MIXED, N](
const BlockSrc& srcs, std::shared_ptr<DependentBlock> self) {
172 for (
int i = 0; i < N; ++i) {
174 double a = srcs.get_val(
"SRC_A",
id);
175 double z = srcs.get_val(
"FUSED_AB",
id);
176 double y = srcs.get_val(
"FUSED_BC",
id);
177 double g = srcs.get_val(
"AVG",
id);
178 double m = 0.5*a + z + 0.1*y -
g;
179 if (self->contains(
id)) self->assign(
id, m);
180 else self->store(
id, std::make_shared<Parameter>(
ParamId(self->get_name(),
id), m, 0., 0.));
184 MIXED->blockname =
"MIXED"; MIXED->set_scale(1.0); MIXED->init();
186 auto REDUCED = std::make_shared<DependentBlock>(
187 std::unordered_map<std::string, std::shared_ptr<Block>>{
190 [&upd_REDUCED, N](
const BlockSrc& srcs, std::shared_ptr<DependentBlock> self) {
193 for (
int i = 0; i < N; ++i) sum += srcs.get_val(
"MIXED",
LhaID(i));
194 if (self->contains(
LhaID(0))) self->assign(
LhaID(0), sum);
195 else self->store(
LhaID(0), std::make_shared<Parameter>(
ParamId(self->get_name(),
LhaID(0)), sum, 0., 0.));
198 REDUCED->blockname =
"REDUCED"; REDUCED->set_scale(1.0); REDUCED->init();
208 MIXED->unfreeze(); MIXED->update();
209 REDUCED->unfreeze(); REDUCED->update();
211 ensure_ready(FUSED_AB, {
LhaID(i1),
LhaID(i2)},
"FUSED_AB needs i1/i2");
212 ensure_ready(FUSED_BC, {
LhaID(i1),
LhaID(i2)},
"FUSED_BC needs i1/i2");
213 ensure_ready(SCALED_A, {
LhaID(j1),
LhaID(j2)},
"SCALED_A needs j1/j2");
214 ensure_ready(MIXED, {
LhaID(j1),
LhaID(j2)},
"MIXED needs j1/j2");
216 upd_FUSED_AB = upd_FUSED_BC = upd_SCALED_A = upd_MIXED = upd_REDUCED = 0;
218 auto DERIVED1 = std::make_shared<Block>(); DERIVED1->blockname =
"DERIVED1"; DERIVED1->set_scale(1.0);
219 auto DERIVED2 = std::make_shared<Block>(); DERIVED2->blockname =
"DERIVED2"; DERIVED2->set_scale(1.0);
221 auto A_i1 = SRC_A->retrieve(
LhaID(i1))->get_id();
222 auto A_i2 = SRC_A->retrieve(
LhaID(i2))->get_id();
223 auto Z_i1 = FUSED_AB->retrieve(
LhaID(i1))->get_id();
224 auto Z_i2 = FUSED_AB->retrieve(
LhaID(i2))->get_id();
225 auto M_j1 = MIXED->retrieve(
LhaID(j1))->get_id();
226 auto M_j2 = MIXED->retrieve(
LhaID(j2))->get_id();
227 auto S_j1 = SCALED_A->retrieve(
LhaID(j1))->get_id();
228 auto S_j2 = SCALED_A->retrieve(
LhaID(j2))->get_id();
230 auto DP_AZ_1 = std::make_shared<DependentParameter>(
232 std::unordered_map<ParamId, std::shared_ptr<Parameter>>{
233 {A_i1, SRC_A->retrieve(
LhaID(i1))}, {Z_i1, FUSED_AB->retrieve(
LhaID(i1))}
235 [A_i1, Z_i1, &upd_DP_AZ_1](
const ParamSrc& src, std::shared_ptr<DependentParameter> self) {
236 ++upd_DP_AZ_1; self->set_expected(src.get_val(A_i1) + src.get_val(Z_i1));
238 ); DP_AZ_1->init(); DERIVED1->store(
LhaID(1001), DP_AZ_1);
240 auto DP_AZ_2 = std::make_shared<DependentParameter>(
242 std::unordered_map<ParamId, std::shared_ptr<Parameter>>{
243 {A_i2, SRC_A->retrieve(
LhaID(i2))}, {Z_i2, FUSED_AB->retrieve(
LhaID(i2))}
245 [A_i2, Z_i2, &upd_DP_AZ_2](
const ParamSrc& src, std::shared_ptr<DependentParameter> self) {
246 ++upd_DP_AZ_2; self->set_expected(src.get_val(A_i2) - src.get_val(Z_i2));
248 ); DP_AZ_2->init(); DERIVED1->store(
LhaID(1002), DP_AZ_2);
250 auto DP_MS_1 = std::make_shared<DependentParameter>(
252 std::unordered_map<ParamId, std::shared_ptr<Parameter>>{
253 {M_j1, MIXED->retrieve(
LhaID(j1))}, {S_j1, SCALED_A->retrieve(
LhaID(j1))}
255 [M_j1, S_j1, &upd_DP_MS_1](
const ParamSrc& src, std::shared_ptr<DependentParameter> self) {
256 ++upd_DP_MS_1; self->set_expected(src.get_val(M_j1) + src.get_val(S_j1));
258 ); DP_MS_1->init(); DERIVED2->store(
LhaID(2001), DP_MS_1);
260 auto DP_MS_2 = std::make_shared<DependentParameter>(
262 std::unordered_map<ParamId, std::shared_ptr<Parameter>>{
263 {M_j2, MIXED->retrieve(
LhaID(j2))}, {S_j2, SCALED_A->retrieve(
LhaID(j2))}
265 [M_j2, S_j2, &upd_DP_MS_2](
const ParamSrc& src, std::shared_ptr<DependentParameter> self) {
266 ++upd_DP_MS_2; self->set_expected(src.get_val(M_j2) - 0.3*src.get_val(S_j2));
268 ); DP_MS_2->init(); DERIVED2->store(
LhaID(2002), DP_MS_2);
270 auto META = std::make_shared<DependentBlock>(
271 std::unordered_map<std::string, std::shared_ptr<Block>>{
272 {
"DERIVED1", DERIVED1}, {
"REDUCED", REDUCED}
274 [&upd_META](
const BlockSrc& srcs, std::shared_ptr<DependentBlock> self) {
276 double v = srcs.get_val(
"DERIVED1",
LhaID(1001))
277 + srcs.get_val(
"DERIVED1",
LhaID(1002))
278 + srcs.get_val(
"REDUCED",
LhaID(0));
279 if (self->contains(
LhaID(0))) self->assign(
LhaID(0), v);
280 else self->store(
LhaID(0), std::make_shared<Parameter>(
ParamId(self->get_name(),
LhaID(0)), v, 0., 0.));
283 META->blockname =
"META"; META->set_scale(1.0); META->init();
286 auto DERIVED_META = std::make_shared<Block>(); DERIVED_META->blockname =
"DERIVED_META"; DERIVED_META->set_scale(1.0);
288 auto S_i1 = SCALED_A->retrieve(
LhaID(i1))->get_id();
290 auto DP_META = std::make_shared<DependentParameter>(
292 std::unordered_map<ParamId, std::shared_ptr<Parameter>>{
293 { META0_id, META->retrieve(
LhaID(0)) },
294 { S_i1, SCALED_A->retrieve(
LhaID(i1)) }
296 [META0_id, S_i1, &upd_DP_META](
const ParamSrc& src, std::shared_ptr<DependentParameter> self) {
298 self->set_expected(src.get_val(META0_id) + src.get_val(S_i1));
300 ); DP_META->init(); DERIVED_META->store(
LhaID(3001), DP_META);
303 print_header(
"INIT (après priming)");
304 dump_block_subset(
"SRC_A", SRC_A, {0,1,2,i1,i2});
305 dump_block_subset(
"SRC_B", SRC_B, {0,1,2,i1,i2});
306 dump_block_subset(
"SRC_C", SRC_C, {0,1,2,i1,i2});
307 dump_block_subset(
"FUSED_AB", FUSED_AB, {0,1,2,i1,i2});
308 dump_block_subset(
"FUSED_BC", FUSED_BC, {0,1,2,i1,i2});
309 dump_block_subset(
"SCALED_A", SCALED_A, {0,1,2,i1,i2});
310 dump_block_subset(
"AVG", AVG, {0,1,2,i1,i2});
311 dump_block_subset(
"MIXED", MIXED, {0,1,2,j1,j2});
312 std::cout <<
"REDUCED[0] = " << fmt(REDUCED->retrieve(
LhaID(0))->get_val()) <<
"\n";
314 auto BA1 = std::make_shared<BlockAccessor>();
315 BA1->emplace(
"SRC_A", SRC_A);
316 BA1->emplace(
"SRC_B", SRC_B);
317 BA1->emplace(
"FUSED_AB", FUSED_AB);
318 BA1->emplace(
"SCALE", SCALE);
319 BA1->emplace(
"SCALED_A", SCALED_A);
320 BA1->emplace(
"AVG", AVG);
322 auto BA2 = std::make_shared<BlockAccessor>();
323 BA2->emplace(
"SRC_C", SRC_C);
324 BA2->emplace(
"FUSED_BC", FUSED_BC);
325 BA2->emplace(
"MIXED", MIXED);
326 BA2->emplace(
"REDUCED", REDUCED);
327 BA2->emplace(
"DERIVED1", DERIVED1);
328 BA2->emplace(
"DERIVED2", DERIVED2);
329 BA2->emplace(
"META", META);
330 BA2->emplace(
"DERIVED_META", DERIVED_META);
334 auto t0 = clock::now();
335 for (
int k = 0; k < OPS; ++k) {
336 int idx = (N ? (k % N) : 0);
337 SRC_A->assign(
LhaID(idx), 0.1*k + std::sin(0.001*k));
338 SRC_B->assign(
LhaID(idx), 0.2*k + std::cos(0.001*k));
339 SRC_C->assign(
LhaID(idx), 0.05*k);
340 if ((k % 200) == 0) SCALE->assign(
LhaID(1), 1.25 + 0.0005*k);
342 if ((k % (OPS/2)) == 0) {
343 print_header(std::string(
"NAIF checkpoint k=") + std::to_string(k));
344 dump_block_subset(
"FUSED_AB", FUSED_AB, {i1,i2});
345 dump_block_subset(
"FUSED_BC", FUSED_BC, {i1,i2});
346 dump_block_subset(
"SCALED_A", SCALED_A, {i1,i2});
347 dump_block_subset(
"MIXED", MIXED, {j1,j2});
348 std::cout <<
"REDUCED[0] = " << fmt(REDUCED->retrieve(
LhaID(0))->get_val()) <<
"\n";
351 auto t1 = clock::now();
352 auto naive_ms = std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0).count();
354 print_header(
"NAIF — résumé");
355 print_kv(
"upd FUSED_AB", std::to_string(upd_FUSED_AB));
356 print_kv(
"upd FUSED_BC", std::to_string(upd_FUSED_BC));
357 print_kv(
"upd SCALED_A", std::to_string(upd_SCALED_A));
358 print_kv(
"upd MIXED", std::to_string(upd_MIXED));
359 print_kv(
"upd REDUCED", std::to_string(upd_REDUCED));
360 print_kv(
"upd DP_AZ_1/2", std::to_string(upd_DP_AZ_1) +
"/" + std::to_string(upd_DP_AZ_2));
361 print_kv(
"upd DP_MS_1/2", std::to_string(upd_DP_MS_1) +
"/" + std::to_string(upd_DP_MS_2));
362 print_kv(
"upd META", std::to_string(upd_META));
363 print_kv(
"time (ms)", std::to_string(naive_ms));
364 dump_block_subset(
"MIXED (post-naif)", MIXED, {j1,j2});
365 std::cout <<
"REDUCED[0] (post-naif) = " << fmt(REDUCED->retrieve(
LhaID(0))->get_val()) <<
"\n";
367 upd_FUSED_AB = upd_FUSED_BC = upd_SCALED_A = upd_MIXED = upd_REDUCED = upd_META = 0;
368 upd_DP_AZ_1 = upd_DP_AZ_2 = upd_DP_MS_1 = upd_DP_MS_2 = upd_DP_META = 0;
370 auto t2 = clock::now();
371 for (
int k = 0; k < OPS; ++k) {
372 int idx = (N ? (k % N) : 0);
373 opt.set_value(
"SRC_A",
LhaID(idx), 0.1*k + std::sin(0.002*k));
374 opt.set_value(
"SRC_B",
LhaID(idx), 0.2*k + std::cos(0.002*k));
375 opt.set_value(
"SRC_C",
LhaID(idx), 0.05*k);
376 if ((k % 200) == 0) opt.set_value(
"SCALE",
LhaID(1), 1.30 + 0.0005*k);
379 auto t3 = clock::now();
380 auto opt_ms = std::chrono::duration_cast<std::chrono::milliseconds>(t3 - t2).count();
382 print_header(
"OPTIMIZER — résumé");
383 print_kv(
"upd FUSED_AB", std::to_string(upd_FUSED_AB));
384 print_kv(
"upd FUSED_BC", std::to_string(upd_FUSED_BC));
385 print_kv(
"upd SCALED_A", std::to_string(upd_SCALED_A));
386 print_kv(
"upd MIXED", std::to_string(upd_MIXED));
387 print_kv(
"upd REDUCED", std::to_string(upd_REDUCED));
388 print_kv(
"upd DP_AZ_1/2", std::to_string(upd_DP_AZ_1) +
"/" + std::to_string(upd_DP_AZ_2));
389 print_kv(
"upd DP_MS_1/2", std::to_string(upd_DP_MS_1) +
"/" + std::to_string(upd_DP_MS_2));
390 print_kv(
"upd META", std::to_string(upd_META));
391 print_kv(
"time (ms)", std::to_string(opt_ms));
392 dump_block_subset(
"MIXED (post-opt)", MIXED, {j1,j2});
393 std::cout <<
"REDUCED[0] (post-opt) = " << fmt(REDUCED->retrieve(
LhaID(0))->get_val()) <<
"\n";
395 auto check_point = [&](
int raw){
397 int idx = ((raw % N) + N) % N;
398 double a = SRC_A->retrieve(
LhaID(idx))->get_val();
399 double b = SRC_B->retrieve(
LhaID(idx))->get_val();
400 double c = SRC_C->retrieve(
LhaID(idx))->get_val();
401 double z = FUSED_AB->retrieve(
LhaID(idx))->get_val();
402 double y = FUSED_BC->retrieve(
LhaID(idx))->get_val();
403 double g = AVG->retrieve(
LhaID(idx))->get_val();
404 double sf = SCALE->retrieve(
LhaID(1))->get_val();
405 double s = SCALED_A->retrieve(
LhaID(idx))->get_val();
406 double m = MIXED->retrieve(
LhaID(idx))->get_val();
407 assert(std::abs(z - (a + 2.0*b)) < 1e-8);
408 assert(std::abs(y - (b - c)) < 1e-8);
409 assert(std::abs(
g - ((a+b+c)/3.0)) < 1e-8);
410 assert(std::abs(s - (sf * a)) < 1e-8);
411 assert(std::abs(m - (0.5*a + z + 0.1*y -
g)) < 1e-8);
413 check_point(0); check_point(1); check_point(i1); check_point(i2);
415 print_header(
"FIN — valeurs clés");
416 dump_block_subset(
"SRC_A", SRC_A, {i1,i2});
417 dump_block_subset(
"FUSED_AB", FUSED_AB, {i1,i2});
418 dump_block_subset(
"SCALED_A", SCALED_A, {j1,j2});
419 dump_block_subset(
"MIXED", MIXED, {j1,j2});
420 std::cout <<
"REDUCED[0] = " << fmt(REDUCED->retrieve(
LhaID(0))->get_val()) <<
"\n";
421 std::cout <<
"DERIVED1[1001] (A[i1]+Z[i1]) = " << fmt(DERIVED1->retrieve(
LhaID(1001))->get_val()) <<
"\n";
422 std::cout <<
"DERIVED1[1002] (A[i2]-Z[i2]) = " << fmt(DERIVED1->retrieve(
LhaID(1002))->get_val()) <<
"\n";
423 std::cout <<
"DERIVED2[2001] (M[j1]+S[j1]) = " << fmt(DERIVED2->retrieve(
LhaID(2001))->get_val()) <<
"\n";
424 std::cout <<
"DERIVED2[2002] (M[j2]-0.3*S[j2]) = " << fmt(DERIVED2->retrieve(
LhaID(2002))->get_val()) <<
"\n";
426 std::cout <<
"\nOK: maillage complexe — prints + cohérence + bench naïf vs opt.\n";