#pragma once #include "pch.h" #pragma strict_gs_...
创建于:2025年8月23日
使用 GPT-5 Thinking 回答 Chat01
创建于:2025年8月23日
使用 GPT-5 Thinking 回答 Chat01
#pragma once
#include "pch.h"
#pragma strict_gs_check(push, off)
#pragma optimize(on)
#pragma inline_recursion(on)
#pragma inline_depth(255u)
#pragma runtime_checks("", off)
#pragma check_stack(off)
#pragma fenv_access(off)
#pragma auto_inline(on)
#pragma managed(push, off)
static __declspec(noalias) __forceinline float xor_rand_grsh(uint32_t& __restrict state) noexcept
{
uint32_t s = state;
s ^= s << 13u;
s ^= s >> 17u;
s ^= s << 5u;
state = s;
return fmaf(s, 0x1.0p-31f, -1.0f);
}
static __declspec(noalias) __forceinline float xor_rand(uint32_t& __restrict state) noexcept
{
uint32_t s = state;
s ^= s << 13u;
s ^= s >> 17u;
s ^= s << 5u;
state = s;
return s * 0x1.0p-32f;
}
static __declspec(noalias) __forceinline float HillFunc(const float x, uint32_t seed) noexcept
{
int32_t i = 0;
__declspec(align(64u)) float angles[14u];
const float start_angle = 6.28318530717958647692f * x;
#pragma loop(ivdep)
while (i < 14) {
angles[i] = start_angle * (i + 1);
++i;
}
text__declspec(align(64u)) float sin_vals[14u]; __declspec(align(64u)) float cos_vals[14u]; fabe13_sincos_scalar_simple(angles, sin_vals, cos_vals, 14u); float res = fmaf(xor_rand(seed), 2.0f, -1.1f); --i; while (i >= 0) { res += fmaf(fmaf(xor_rand(seed), 2.0f, -1.1f), sin_vals[i], fmaf(xor_rand(seed), 2.0f, -1.1f) * cos_vals[i]); --i; } return res;
}
static __declspec(noalias) __forceinline float ShekelFunc(const float x, uint32_t seed) noexcept
{
uint32_t i = 0u;
float res = 0.0f;
textwhile (i < 10u) { const float r = xor_rand(seed); const float x_part = fmaf(-r, 10.0f, x); res -= 1.0f / fmaf(fmaf(xor_rand(seed), 20.0f, 0.5f), x_part * x_part, fmaf(xor_rand(seed), 0.4f, 1.0f)); ++i; } return res;
}
static __declspec(noalias) __forceinline float GrishaginFunc(const float x1, const float x2, uint32_t seed) noexcept
{
int32_t i = 0;
__declspec(align(64u)) float angles_i[8u];
__declspec(align(64u)) float angles_j[8u];
#pragma loop(ivdep)
while (i < 8) {
const float pi_mult = 3.14159265358979323846f * (i + 1);
angles_i[i] = pi_mult * x1;
angles_j[i] = pi_mult * x2;
++i;
}
text__declspec(align(64u)) float sin_i[8u], cos_i[8u]; __declspec(align(64u)) float sin_j[8u], cos_j[8u]; fabe13_sincos_scalar_simple(angles_i, sin_i, cos_i, 8u); fabe13_sincos_scalar_simple(angles_j, sin_j, cos_j, 8u); --i; float part1 = 0.0f; float part2 = 0.0f; while (i >= 0) { uint32_t j = 0u; while (j < 8u) { const float sin_term = sin_i[i] * sin_i[i]; const float cos_term = cos_j[j] * cos_j[j]; part1 = fmaf(xor_rand_grsh(seed), sin_term, fmaf(xor_rand_grsh(seed), cos_term, part1)); part2 = fmaf(-xor_rand_grsh(seed), cos_term, fmaf(xor_rand_grsh(seed), sin_term, part2)); ++j; } --i; } return -sqrtf(fmaf(part1, part1, part2 * part2));
}
static __declspec(noalias) __forceinline float RastriginFunc(const float x1, const float x2) noexcept
{
const float term1 = fmaf(x1, x1, x2 * x2);
return (term1 - fmaf(
fabe13_cos(6.28318530717958647692f * x1) +
fabe13_cos(6.28318530717958647692f * x2),
10.0f,
-14.6f)) *
fmaf(-term1, 0.25f, 18.42f);
}
static __declspec(noalias) __forceinline float Shag(const float _m, const float x1, const float x2, const float y1,
const float y2, const uint32_t _N, const float _r) noexcept
{
const float diff = y2 - y1;
return _N == 1u
? fmaf(-(1.0f / _m), diff, x1 + x2) * 0.5f
: diff > 0u
? fmaf(-(1.0f / (_m * _m)), (diff) * (diff)_r, x1 + x2) * 0.5f
: fmaf(1.0f / (_m * _m), (diff) * (diff)_r, x1 + x2) * 0.5f;
}
const __declspec(align(32u)) struct Interval final
{
public:
std::pair<float, float> start;
std::pair<float, float> end;
float M;
float R;
text__declspec(noalias) __forceinline Interval(const std::pair<float, float>& __restrict _start, const std::pair<float, float>& __restrict _end, const uint32_t _N) noexcept : start(_start) , end(_end) , M(_N == 1u ? fabsf(_end.second - _start.second) / (_end.first - _start.first) : _N == 2u ? fabsf(_end.second - _start.second) / sqrtf(_end.first - _start.first) : fabsf(_end.second - _start.second) / powf(_end.first - _start.first, 1.0f / float(_N))) { } const __declspec(noalias) __forceinline void ChangeCharacteristic(const float _m, const uint32_t _N) noexcept { const float delta_x = end.first - start.first; const float delta_y = end.second - start.second; switch (_N) { case 1u: R = fmaf( -(end.second + start.second), 2.0f, fmaf(_m, delta_x, (delta_y * delta_y) / (_m * delta_x))); break; case 2u: { const float sqrt_dx = sqrtf(delta_x); R = fmaf( -(end.second + start.second), 2.0f, fmaf(_m, sqrt_dx, (delta_y * delta_y) / (_m * sqrt_dx))); } break; default: { const float pow_dx = powf(delta_x, 1.0f / _N); R = fmaf( -(end.second + start.second), 2.0f, fmaf(_m, pow_dx, (delta_y * delta_y) / (_m * pow_dx))); } } }
};
static __declspec(noalias) __forceinline bool Compare(const Interval& __restrict a, const Interval& __restrict b) noexcept
{
return a.R < b.R;
}
const __declspec(noalias) __forceinline PeanoCurve_2D* PeanoCurve_2D::HitTest_2D(float x) const noexcept
{
uint32_t i = 0u;
const uint32_t _razvertka = this->razvertka;
uint32_t num;
const float this_a = this->a;
x -= this_a;
const float b_minus_a = this->b - this_a;
const float inv_b_minus_a = 1.0f / b_minus_a;
const PeanoCurve_2D* Curr = this;
textwhile (i != _razvertka) { const uint32_t shift = 1u << ++i + i; num = shift * x * inv_b_minus_a; x = fmaf(-ldexp(1.0f, -(i << 1)) * num, b_minus_a, x); const List currType = Curr->Type; switch (num) { case 0u: Curr = (currType == Top || currType == Right) ? Curr->DownLeft.get() : Curr->TopRight.get(); break; case 1u: Curr = (currType == Top || currType == Left) ? Curr->TopLeft.get() : Curr->DownRight.get(); break; case 2u: Curr = (currType == Top || currType == Right) ? Curr->TopRight.get() : Curr->DownLeft.get(); break; case 3u: Curr = (currType == Top || currType == Left) ? Curr->DownRight.get() : Curr->TopLeft.get(); } } return Curr;
}
const __declspec(noalias) __forceinline float PeanoCurve_2D::FindX_2D(float target_x1, float target_x2) const noexcept
{
uint32_t _razvertka = this->razvertka;
uint32_t _razvertka1 = _razvertka;
float x1, x2, x = this->a;
const float b_minus_a = this->b - x;
const PeanoCurve_2D* Curr = this;
textwhile (_razvertka != 0u) { const uint32_t exponent = _razvertka1 - _razvertka-- << 1u; x1 = Curr->x1; x2 = Curr->x2; const List currType = Curr->Type; if (target_x1 > x1 && target_x2 > x2) { Curr = Curr->TopRight.get(); if (currType == Top || currType == Right) { x = fmaf(ldexp(1.0f, -exponent) * 0.5f, b_minus_a, x); } } else if (target_x1 < x1 && target_x2 > x2) { Curr = Curr->TopLeft.get(); if (currType == Top || currType == Left) { x = fmaf(ldexp(1.0f, -exponent) * 0.25f, b_minus_a, x); } else { x = fmaf(ldexp(1.0f, -exponent) * 0.75f, b_minus_a, x); } } else if (target_x1 < x1 && target_x2 < x2) { Curr = Curr->DownLeft.get(); if (currType == Down || currType == Left) { x = fmaf(ldexp(1.0f, -exponent) * 0.5f, b_minus_a, x); } } else { Curr = Curr->DownRight.get(); if (currType == Top || currType == Left) { x = fmaf(ldexp(1.0f, -exponent) * 0.75f, b_minus_a, x); } else { x = fmaf(ldexp(1.0f, -exponent) * 0.25f, b_minus_a, x); } } } return x;
}
extern const boost::mpi::communicator world;
extern std::unique_ptr<PeanoCurve_2D> Curve;
extern std::unique_ptr<PeanoCurve_2D> Curve_Inverted;
__declspec(dllexport) __declspec(noalias) std::vector<float> Base_LNA_1_2_Mer_AGP(const uint32_t N,
const uint32_t global_iterations, const float a, const float b, const float c, const float d, const uint32_t r,
const bool mode, const float epsilon, const uint32_t seed) noexcept
{
if (N == 1u) {
const float initial_length = b - a;
float dmax = initial_length;
textstd::vector<float> Extr; Extr.reserve((global_iterations << 1u) + 2u); std::vector<Interval> R; R.reserve(global_iterations + 1u); float best_f = ShekelFunc(a, seed); const float end_val = ShekelFunc(b, seed); uint32_t schetchick = 0u; std::pair<float, float> x_Rmax = std::make_pair(a, b); std::pair<float, float> y_Rmax = std::make_pair(best_f, end_val); R.emplace_back(std::make_pair(a, best_f), std::make_pair(b, end_val), N); float Mmax = R.front().M; float m = r * Mmax; while (true) { if (++schetchick == global_iterations) { const Interval& front = R.front(); Extr.emplace_back(front.end.first - front.start.first); Extr.emplace_back(global_iterations); return Extr; } const float x1 = x_Rmax.first; const float x2 = x_Rmax.second; const float y1 = y_Rmax.first; const float y2 = y_Rmax.second; const float new_point = Shag(m, x1, x2, y1, y2, N, r); const float new_value = ShekelFunc(new_point, seed); const std::pair<float, float> promejutochnaya_tochka = std::make_pair(new_point, new_value); if (new_value < best_f) { best_f = new_value; Extr.emplace_back(best_f); Extr.emplace_back(new_point); } std::pop_heap(R.begin(), R.end(), Compare); const Interval promejutochny_otrezok = std::move(R.back()); R.pop_back(); Interval curr(promejutochny_otrezok.start, promejutochnaya_tochka, N); Interval curr1(promejutochnaya_tochka, promejutochny_otrezok.end, N); const float currM = curr.M > curr1.M ? curr.M : curr1.M; const float len2 = promejutochny_otrezok.end.first - new_point; const float len1 = new_point - promejutochny_otrezok.start.first; const size_t r_size = R.size(); if (len2 + len1 == dmax) { dmax = len2 > len1 ? len2 : len1;
#pragma loop(ivdep)
for (size_t i = 0u; i < r_size; ++i) {
const float len = R[i].end.first - R[i].start.first;
if (len > dmax) {
dmax = len;
}
}
}
textif (mode) { const float threshold_03 = 0.3f * initial_length; if (threshold_03 > dmax && schetchick % 3u == 0u || 10.0f * dmax < initial_length) { if (currM > Mmax) { Mmax = currM; m = r * Mmax; } const float inv_threshold_03 = 1.0f / threshold_03; const float progress = fmaf(-inv_threshold_03, dmax, 1.0f); const float alpha = fmaf(progress, progress, 1.0f); const float betta = 2.0f - alpha; const float inv_dmax = 1.0f / dmax; const float MULTIPLIER = inv_dmax * Mmax; const float global_coeff = fmaf(MULTIPLIER, r, -MULTIPLIER); const float GLOBAL_FACTOR = betta * global_coeff; curr.ChangeCharacteristic(fmaf(GLOBAL_FACTOR, len1, curr.M * alpha), N); curr1.ChangeCharacteristic(fmaf(GLOBAL_FACTOR, len2, curr1.M * alpha), N);
#pragma loop(ivdep)
for (size_t i = 0u; i < r_size; ++i) {
const float len_item = R[i].end.first - R[i].start.first;
R[i].ChangeCharacteristic(fmaf(GLOBAL_FACTOR, len_item, R[i].M * alpha), N);
}
std::make_heap(R.begin(), R.end(), Compare);
} else {
if (currM > Mmax) {
Mmax = currM;
m = r * Mmax;
curr.ChangeCharacteristic(m, N);
curr1.ChangeCharacteristic(m, N);
#pragma loop(ivdep)
for (size_t i = 0u; i < r_size; ++i) {
R[i].ChangeCharacteristic(m, N);
}
std::make_heap(R.begin(), R.end(), Compare);
} else {
curr.ChangeCharacteristic(m, N);
curr1.ChangeCharacteristic(m, N);
}
}
} else {
if (currM > Mmax) {
Mmax = currM;
m = r * Mmax;
curr.ChangeCharacteristic(m, N);
curr1.ChangeCharacteristic(m, N);
#pragma loop(ivdep)
for (size_t i = 0u; i < r_size; ++i) {
R[i].ChangeCharacteristic(m, N);
}
std::make_heap(R.begin(), R.end(), Compare);
} else {
curr.ChangeCharacteristic(m, N);
curr1.ChangeCharacteristic(m, N);
}
}
textR.emplace_back(std::move(curr)); std::push_heap(R.begin(), R.end(), Compare); R.emplace_back(std::move(curr1)); std::push_heap(R.begin(), R.end(), Compare); const Interval& top = R.front(); const float interval_length = top.end.first - top.start.first; if (interval_length < epsilon) { Extr.emplace_back(interval_length); Extr.emplace_back(schetchick); return Extr; } x_Rmax = std::make_pair(top.start.first, top.end.first); y_Rmax = std::make_pair(top.start.second, top.end.second); } } else { std::vector<float> Extr; Extr.reserve(3u * global_iterations + 2u); std::vector<Interval> R; R.reserve(global_iterations + 1u); std::vector<Interval> R_Inverted; R_Inverted.reserve(global_iterations + 1u); const float divider = 1u << (2u * Curve_Inverted->razvertka + 1u); const float x_addition = (b - a) / divider; const float y_addition = (d - c) / divider; const float true_start = a + x_addition; const float true_end = b - x_addition; const float initial_length = true_end - true_start; float dmax = initial_length; float dmax_Inverted = initial_length; uint32_t schetchick = 0u; const std::pair<float, float> start = std::make_pair(true_start, RastriginFunc(true_start, c + y_addition)); const std::pair<float, float> end = std::make_pair(true_end, RastriginFunc(true_end, c + y_addition)); const std::pair<float, float> start_Inverted = std::make_pair(true_start, RastriginFunc(true_end, d - y_addition)); const std::pair<float, float> end_Inverted = std::make_pair(true_end, RastriginFunc(true_start, d - y_addition)); std::pair<float, float> x_Rmax = std::make_pair(start.first, end.first); std::pair<float, float> y_Rmax = std::make_pair(start.second, end.second); std::pair<float, float> x_Rmax_Inverted = std::make_pair(start_Inverted.first, end_Inverted.first); std::pair<float, float> y_Rmax_Inverted = std::make_pair(start_Inverted.second, end_Inverted.second); float best_f = end_Inverted.second; Interval initial_interval(start, end, N); Interval initial_interval_Inverted(start_Inverted, end_Inverted, N); float Mmax = initial_interval.M; float Mmax_Inverted = initial_interval_Inverted.M; float m = r * Mmax; float m_Inverted = r * Mmax_Inverted; R.emplace_back(std::move(initial_interval)); R_Inverted.emplace_back(std::move(initial_interval_Inverted)); while (true) { if (++schetchick == global_iterations) { const Interval& topA = R.front(); const Interval& topB = R_Inverted.front(); const float lenA = topA.end.first - topA.start.first; const float lenB = topB.end.first - topB.start.first; const float interval_length = lenA > lenB ? lenA : lenB; Extr.emplace_back(interval_length); Extr.emplace_back(global_iterations); return Extr; } const float x1A = x_Rmax.first; const float x2A = x_Rmax.second; const float y1A = y_Rmax.first; const float y2A = y_Rmax.second; const float x1B = x_Rmax_Inverted.first; const float x2B = x_Rmax_Inverted.second; const float y1B = y_Rmax_Inverted.first; const float y2B = y_Rmax_Inverted.second; const float new_param_A = Shag(m, x1A, x2A, y1A, y2A, N, r); const float new_param_B = Shag(m_Inverted, x1B, x2B, y1B, y2B, N, r); const float cooling = expf(-schetchick / 200.0f); const uint32_t T = fmaf(20.0f, cooling, 10.0f); const float k = fmaf(0.2f, cooling, 0.7f); const PeanoCurve_2D* pA = Curve->HitTest_2D(new_param_A); const PeanoCurve_2D* pB = Curve_Inverted->HitTest_2D(new_param_B); if (schetchick % T == 0u && schetchick > T && !R.empty() && !R_Inverted.empty()) { const Interval& topA = R.front(); const Interval& topB = R_Inverted.front(); const PeanoCurve_2D* p1A = Curve->HitTest_2D(topA.start.first); const PeanoCurve_2D* p2A = Curve->HitTest_2D(topA.end.first); const PeanoCurve_2D* p1B = Curve_Inverted->HitTest_2D(topB.start.first); const PeanoCurve_2D* p2B = Curve_Inverted->HitTest_2D(topB.end.first); const float newParam1_B = Curve->FindX_2D(p1B->x1, p1B->x2); const float newParam2_B = Curve->FindX_2D(p2B->x1, p2B->x2); const float newParam1_A = Curve_Inverted->FindX_2D(p1A->x1, p1A->x2); const float newParam2_A = Curve_Inverted->FindX_2D(p2A->x1, p2A->x2); const std::pair<float, float> newStart_A(newParam1_A, topA.start.second); const std::pair<float, float> newEnd_A(newParam2_A, topA.end.second); const std::pair<float, float> newStart_B(newParam1_B, topB.start.second); const std::pair<float, float> newEnd_B(newParam2_B, topB.end.second); Interval injected_A(newStart_A, newEnd_A, N); Interval injected_B(newStart_B, newEnd_B, N); injected_A.R = topA.R * k; injected_B.R = topB.R * k; R.emplace_back(std::move(injected_B)); std::push_heap(R.begin(), R.end(), Compare); R_Inverted.emplace_back(std::move(injected_A)); std::push_heap(R_Inverted.begin(), R_Inverted.end(), Compare); } const float new_x1_A = pA->x1; const float new_x2_A = pA->x2; const float new_x1_B = pB->x1; const float new_x2_B = pB->x2; const float new_value_A = RastriginFunc(new_x1_A, new_x2_A); const float new_value_B = RastriginFunc(new_x1_B, new_x2_B); const std::pair<float, float> promejutochnaya_tochka_A = std::make_pair(new_param_A, new_value_A); const std::pair<float, float> promejutochnaya_tochka_B = std::make_pair(new_param_B, new_value_B); if (new_value_A < best_f) { best_f = new_value_A; if (new_value_B < best_f) { best_f = new_value_B; Extr.emplace_back(best_f); Extr.emplace_back(new_x1_B); Extr.emplace_back(new_x2_B); } else { Extr.emplace_back(best_f); Extr.emplace_back(new_x1_A); Extr.emplace_back(new_x2_A); } } else if (new_value_B < best_f) { best_f = new_value_B; Extr.emplace_back(best_f); Extr.emplace_back(new_x1_B); Extr.emplace_back(new_x2_B); } std::pop_heap(R.begin(), R.end(), Compare); const Interval promejutochny_otrezok_A = std::move(R.back()); R.pop_back(); std::pop_heap(R_Inverted.begin(), R_Inverted.end(), Compare); const Interval promejutochny_otrezok_B = std::move(R_Inverted.back()); R_Inverted.pop_back(); Interval curr_A(promejutochny_otrezok_A.start, promejutochnaya_tochka_A, N); Interval curr1_A(promejutochnaya_tochka_A, promejutochny_otrezok_A.end, N); Interval curr_B(promejutochny_otrezok_B.start, promejutochnaya_tochka_B, N); Interval curr1_B(promejutochnaya_tochka_B, promejutochny_otrezok_B.end, N); const float currM_A = curr1_A.M > curr_A.M ? curr1_A.M : curr_A.M; const float currM_B = curr1_B.M > curr_B.M ? curr1_B.M : curr_B.M; const float len2_A = promejutochny_otrezok_A.end.first - new_param_A; const float len1_A = new_param_A - promejutochny_otrezok_A.start.first; const float len2_B = promejutochny_otrezok_B.end.first - new_param_B; const float len1_B = new_param_B - promejutochny_otrezok_B.start.first; const size_t r_size = R.size(); if (len2_A + len1_A == dmax) { dmax = len2_A > len1_A ? len2_A : len1_A;
#pragma loop(ivdep)
for (size_t i = 0u; i < r_size; ++i) {
const float l = R[i].end.first - R[i].start.first;
if (l > dmax) {
dmax = l;
}
}
}
if (len2_B + len1_B == dmax_Inverted) {
dmax_Inverted = len2_B > len1_B ? len2_B : len1_B;
#pragma loop(ivdep)
for (size_t i = 0u; i < r_size; ++i) {
const float l = R_Inverted[i].end.first - R_Inverted[i].start.first;
if (l > dmax_Inverted) {
dmax_Inverted = l;
}
}
}
textif (mode) { const float threshold_03 = 0.3f * initial_length; if (threshold_03 > dmax && schetchick % 3u == 0u || 10.0f * dmax < initial_length) { if (currM_A > Mmax) { Mmax = currM_A; m = r * Mmax; } const float inv_threshold_03 = 1.0f / threshold_03; const float progress = fmaf(-inv_threshold_03, dmax, 1.0f); const float alpha = fmaf(progress, progress, 1.0f); const float betta = 2.0f - alpha; const float inv_dmax = 1.0f / dmax; const float MULTIPLIER = inv_dmax * Mmax; const float global_coeff = fmaf(MULTIPLIER, r, -MULTIPLIER); const float GLOBAL_FACTOR = betta * global_coeff; curr_A.ChangeCharacteristic(fmaf(GLOBAL_FACTOR, len1_A, curr_A.M * alpha), N); curr1_A.ChangeCharacteristic(fmaf(GLOBAL_FACTOR, len2_A, curr1_A.M * alpha), N);
#pragma loop(ivdep)
for (size_t i = 0u; i < r_size; ++i) {
const float li = R[i].end.first - R[i].start.first;
R[i].ChangeCharacteristic(fmaf(GLOBAL_FACTOR, li, R[i].M * alpha), N);
}
std::make_heap(R.begin(), R.end(), Compare);
} else {
if (currM_A > Mmax) {
Mmax = currM_A;
m = r * Mmax;
curr_A.ChangeCharacteristic(m, N);
curr1_A.ChangeCharacteristic(m, N);
#pragma loop(ivdep)
for (size_t i = 0u; i < r_size; ++i) {
R[i].ChangeCharacteristic(m, N);
}
std::make_heap(R.begin(), R.end(), Compare);
} else {
curr_A.ChangeCharacteristic(m, N);
curr1_A.ChangeCharacteristic(m, N);
}
}
textif (threshold_03 > dmax_Inverted && schetchick % 3u == 0u || 10.0f * dmax_Inverted < initial_length) { if (currM_B > Mmax_Inverted) { Mmax_Inverted = currM_B; m_Inverted = r * Mmax_Inverted; } const float inv_threshold_03 = 1.0f / threshold_03; const float progress = fmaf(-inv_threshold_03, dmax_Inverted, 1.0f); const float alpha = fmaf(progress, progress, 1.0f); const float betta = 2.0f - alpha; const float inv_dmax = 1.0f / dmax_Inverted; const float MULTIPLIER = inv_dmax * Mmax_Inverted; const float global_coeff = fmaf(MULTIPLIER, r, -MULTIPLIER); const float GLOBAL_FACTOR = betta * global_coeff; curr_B.ChangeCharacteristic(fmaf(GLOBAL_FACTOR, len1_B, curr_B.M * alpha), N); curr1_B.ChangeCharacteristic(fmaf(GLOBAL_FACTOR, len2_B, curr1_B.M * alpha), N);
#pragma loop(ivdep)
for (size_t i = 0u; i < r_size; ++i) {
const float li = R_Inverted[i].end.first - R_Inverted[i].start.first;
R_Inverted[i].ChangeCharacteristic(fmaf(GLOBAL_FACTOR, li, R_Inverted[i].M * alpha), N);
}
std::make_heap(R_Inverted.begin(), R_Inverted.end(), Compare);
} else {
if (currM_B > Mmax_Inverted) {
Mmax_Inverted = currM_B;
m_Inverted = r * Mmax_Inverted;
curr_B.ChangeCharacteristic(m_Inverted, N);
curr1_B.ChangeCharacteristic(m_Inverted, N);
#pragma loop(ivdep)
for (size_t i = 0u; i < r_size; ++i) {
R_Inverted[i].ChangeCharacteristic(m_Inverted, N);
}
std::make_heap(R_Inverted.begin(), R_Inverted.end(), Compare);
} else {
curr_B.ChangeCharacteristic(m_Inverted, N);
curr1_B.ChangeCharacteristic(m_Inverted, N);
}
}
} else {
if (currM_A > Mmax) {
Mmax = currM_A;
m = r * Mmax;
curr_A.ChangeCharacteristic(m, N);
curr1_A.ChangeCharacteristic(m, N);
#pragma loop(ivdep)
for (size_t i = 0u; i < r_size; ++i) {
R[i].ChangeCharacteristic(m, N);
}
std::make_heap(R.begin(), R.end(), Compare);
} else {
curr_A.ChangeCharacteristic(m, N);
curr1_A.ChangeCharacteristic(m, N);
}
textif (currM_B > Mmax_Inverted) { Mmax_Inverted = currM_B; m_Inverted = r * Mmax_Inverted; curr_B.ChangeCharacteristic(m_Inverted, N); curr1_B.ChangeCharacteristic(m_Inverted, N);
#pragma loop(ivdep)
for (size_t i = 0u; i < r_size; ++i) {
R_Inverted[i].ChangeCharacteristic(m_Inverted, N);
}
std::make_heap(R_Inverted.begin(), R_Inverted.end(), Compare);
} else {
curr_B.ChangeCharacteristic(m_Inverted, N);
curr1_B.ChangeCharacteristic(m_Inverted, N);
}
}
textR.emplace_back(std::move(curr_A)); std::push_heap(R.begin(), R.end(), Compare); R.emplace_back(std::move(curr1_A)); std::push_heap(R.begin(), R.end(), Compare); R_Inverted.emplace_back(std::move(curr_B)); std::push_heap(R_Inverted.begin(), R_Inverted.end(), Compare); R_Inverted.emplace_back(std::move(curr1_B)); std::push_heap(R_Inverted.begin(), R_Inverted.end(), Compare); const Interval& topA = R.front(); const Interval& topB = R_Inverted.front(); const float interval_length_A = topA.end.first - topA.start.first; const float interval_length_B = topB.end.first - topB.start.first; const float interval_length = interval_length_A > interval_length_B ? interval_length_A : interval_length_B; if (interval_length < epsilon) { Extr.emplace_back(interval_length); Extr.emplace_back(schetchick); return Extr; } x_Rmax = std::make_pair(topA.start.first, topA.end.first); y_Rmax = std::make_pair(topA.start.second, topA.end.second); x_Rmax_Inverted = std::make_pair(topB.start.first, topB.end.first); y_Rmax_Inverted = std::make_pair(topB.start.second, topB.end.second); } }
} рассмотри здесь вторую ветвь алгоритма - её нужно распараллелить через boost::mpi следующим образом, всё что происходит на обычной развёртке - выполняется на процессе с рангом 0, всё что на перевёрнутой развёртке на процессе с рангом 1, вычисления, обработки интервалов, циклы, изменения характеристик и т д - все эти вычисления должны происходить полностью изолированно независимо, развёртки должны сообщаться между собой в момент кросс инъекций в соответствии с правилом когда эти кросс инъекции должны наступать, возможно ещё развёртки должны сообщаться между собой в момент обновления лучшей точки - хотя это под вопросом, так как это может быть слишком дорого, правило останова можно сделать таким - счёт останавливается когда остановила счёт одна из развёрток на одном из процессов, сам MPI контекст у меня задаётся во время загрузки этой DLL библиотеки так: #include "pch.h"
const boost::mpi::environment mpi_env;
const boost::mpi::communicator world;
std::unique_ptr<PeanoCurve_2D> Curve;
std::unique_ptr<PeanoCurve_2D> Curve_Inverted;
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
const int32_t rank = world.rank();
if (rank == 0) {
Curve = std::make_unique<PeanoCurve_2D>(List::Top, 12, -2.2f, 1.8f, -2.2f, 1.8f);
}
else if (rank == 1) {
Curve_Inverted = std::make_unique<PeanoCurve_2D>(List::Down, 12, -2.2f, 1.8f, -2.2f, 1.8f);
}
}
return TRUE;
}, само построение деревьев оставь в моменте загрузки библиотеки оно там и должно происходить один раз, само построение деревьев выполняется параллельно через TBB: #pragma once
#include <cstdint>
#include <memory>
#include <oneapi/tbb/parallel_invoke.h>
const enum List : uint8_t {
Top = 0b00,
Down = 0b01,
Left = 0b10,
Right = 0b11
};
const __declspec(align(64u)) struct PeanoCurve_2D final {
public:
const List Type;
const uint32_t razvertka;
const float a;
const float b;
const float c;
const float d;
const float x1;
const float x2;
std::unique_ptr<PeanoCurve_2D> DownLeft;
std::unique_ptr<PeanoCurve_2D> TopLeft;
std::unique_ptr<PeanoCurve_2D> TopRight;
std::unique_ptr<PeanoCurve_2D> DownRight;
text__declspec(noalias) __forceinline PeanoCurve_2D( const List _Type, uint32_t _razvertka, const float _a, const float _b, const float _c, const float _d) noexcept : Type(_Type), razvertka(_razvertka), a(_a), b(_b), c(_c), d(_d), x1(fmaf(0.5f, _a, 0.5f * _b)), x2(fmaf(0.5f, _c, 0.5f * _d)) { if (_razvertka-- != 0u) { if (_razvertka > 8u) { switch (_Type) { case Top: tbb::parallel_invoke( [&]() { DownLeft = std::make_unique<PeanoCurve_2D>(Right, _razvertka, _a, x1, _c, x2); }, [&]() { TopLeft = std::make_unique<PeanoCurve_2D>(Top, _razvertka, _a, x1, x2, _d); }, [&]() { TopRight = std::make_unique<PeanoCurve_2D>(Top, _razvertka, x1, _b, x2, _d); }, [&]() { DownRight = std::make_unique<PeanoCurve_2D>(Left, _razvertka, x1, _b, _c, x2); } ); break; case Down: tbb::parallel_invoke( [&]() { TopRight = std::make_unique<PeanoCurve_2D>(Left, _razvertka, x1, _b, x2, _d); }, [&]() { DownRight = std::make_unique<PeanoCurve_2D>(Down, _razvertka, x1, _b, _c, x2); }, [&]() { DownLeft = std::make_unique<PeanoCurve_2D>(Down, _razvertka, _a, x1, _c, x2); }, [&]() { TopLeft = std::make_unique<PeanoCurve_2D>(Right, _razvertka, _a, x1, x2, _d); } ); break; case Right: tbb::parallel_invoke( [&]() { DownLeft = std::make_unique<PeanoCurve_2D>(Top, _razvertka, _a, x1, _c, x2); }, [&]() { DownRight = std::make_unique<PeanoCurve_2D>(Right, _razvertka, x1, _b, _c, x2); }, [&]() { TopRight = std::make_unique<PeanoCurve_2D>(Right, _razvertka, x1, _b, x2, _d); }, [&]() { TopLeft = std::make_unique<PeanoCurve_2D>(Down, _razvertka, _a, x1, x2, _d); } ); break; case Left: tbb::parallel_invoke( [&]() { TopRight = std::make_unique<PeanoCurve_2D>(Down, _razvertka, x1, _b, x2, _d); }, [&]() { TopLeft = std::make_unique<PeanoCurve_2D>(Left, _razvertka, _a, x1, x2, _d); }, [&]() { DownLeft = std::make_unique<PeanoCurve_2D>(Left, _razvertka, _a, x1, _c, x2); }, [&]() { DownRight = std::make_unique<PeanoCurve_2D>(Top, _razvertka, x1, _b, _c, x2); } ); } } else { switch (_Type) { case Top: DownLeft = std::make_unique<PeanoCurve_2D>(Right, _razvertka, _a, x1, _c, x2); TopLeft = std::make_unique<PeanoCurve_2D>(Top, _razvertka, _a, x1, x2, _d); TopRight = std::make_unique<PeanoCurve_2D>(Top, _razvertka, x1, _b, x2, _d); DownRight = std::make_unique<PeanoCurve_2D>(Left, _razvertka, x1, _b, _c, x2); break; case Down: TopRight = std::make_unique<PeanoCurve_2D>(Left, _razvertka, x1, _b, x2, _d); DownRight = std::make_unique<PeanoCurve_2D>(Down, _razvertka, x1, _b, _c, x2); DownLeft = std::make_unique<PeanoCurve_2D>(Down, _razvertka, _a, x1, _c, x2); TopLeft = std::make_unique<PeanoCurve_2D>(Right, _razvertka, _a, x1, x2, _d); break; case Right: DownLeft = std::make_unique<PeanoCurve_2D>(Top, _razvertka, _a, x1, _c, x2); DownRight = std::make_unique<PeanoCurve_2D>(Right, _razvertka, x1, _b, _c, x2); TopRight = std::make_unique<PeanoCurve_2D>(Right, _razvertka, x1, _b, x2, _d); TopLeft = std::make_unique<PeanoCurve_2D>(Down, _razvertka, _a, x1, x2, _d); break; case Left: TopRight = std::make_unique<PeanoCurve_2D>(Down, _razvertka, x1, _b, x2, _d); TopLeft = std::make_unique<PeanoCurve_2D>(Left, _razvertka, _a, x1, x2, _d); DownLeft = std::make_unique<PeanoCurve_2D>(Left, _razvertka, _a, x1, _c, x2); DownRight = std::make_unique<PeanoCurve_2D>(Top, _razvertka, x1, _b, _c, x2); } } } } const __declspec(noalias) __forceinline PeanoCurve_2D* HitTest_2D(float x) const noexcept; const __declspec(noalias) __forceinline float FindX_2D(float target_x1, float target_x2) const noexcept;
}; мне верни изменённый код для двумерной ветки через boost::mpi распараллеленный - также напиши какие заголовки дополнительно понадобятся, также обрати внимание на локальность данных - все переменные расположены не просто так а из соображений лучшей локальности данных - так что учитывай это при распараллеливании и сохраняй хорошую локальность данных, следи чтобы твой код не слишком сильно отходил от моих канонов, то что будет происходить на каждом процессе алгоритмически не должно отличаться слишком сильно от того что происходит в последовательной версии одномерной ветки, в конце дай дополнительные советы по оптимизации но не вноси их в код
ниже — готовая замена только для двумерной ветки (else
у if (N == 1u)
), распараллеленная на два процесса Boost.MPI по вашему правилу:
0
считает «обычную» развёртку (Curve
),1
считает перевёрнутую развёртку (Curve_Inverted
),all_reduce(max)
над флагом останова.В односторонней инъекции каждый процесс конвертирует полученные от напарника граничные точки в свой параметр с помощью своей кривой Пеано, формирует «впрыснутый» интервал и помещает его в свою кучу; значение
R
для «впрыснутого» интервала берётся какk * R_top_партнёра
(его мы передаём во вложении к координатам). Значенияy
для концов «впрыснутого» интервала мы пересчитываем локально черезRastriginFunc
по присланным — это эквивалентно оригиналу (функция та же, точки те же), при этом нам не нужно передаватьy
.
Base_LNA_1_2_Mer_AGP
— двумерная ветка)cpp// ... начало функции Base_LNA_1_2_Mer_AGP(...) остаётся без изменений ... } else { // ====== N != 1u : 2D ветка, распараллелено по Boost.MPI ====== struct CrossMsg final { float s_x1, s_x2; // start: (x1,x2) float e_x1, e_x2; // end : (x1,x2) float Rtop; // R-характеристика вершины отправителя // Boost.Serialization template <typename Archive> void serialize(Archive& ar, const unsigned int) { ar & s_x1 & s_x2 & e_x1 & e_x2 & Rtop; } }; const int32_t rank = world.rank(); const int32_t partner = (rank ^ 1); // Выбор локальной развёртки и начальных граничных условий — строго как у вас, но разнесено по рангам. const PeanoCurve_2D* __restrict LocCurve = (rank == 0) ? Curve.get() : Curve_Inverted.get(); std::vector<float> Extr; Extr.reserve(3u * global_iterations + 2u); std::vector<Interval> R; R.reserve(global_iterations + 1u); // Геометрия «защитной рамки» как в исходнике: одинаковая для обоих рангов. const float divider = 1u << (2u * (LocCurve ? LocCurve->razvertka : 0u) + 1u); const float x_addition = (b - a) / divider; const float y_addition = (d - c) / divider; const float true_start = a + x_addition; const float true_end = b - x_addition; const float initial_length = true_end - true_start; float dmax = initial_length; uint32_t schetchick = 0u; // Стартовые точки и значения — согласно вашей «двойной» логике, // но каждая ветка инициализирует свою сторону. std::pair<float, float> start, end; if (rank == 0) { // Обычная развёртка (Curve) start = std::make_pair(true_start, RastriginFunc(true_start, c + y_addition)); end = std::make_pair(true_end, RastriginFunc(true_end, c + y_addition)); } else { // Перевёрнутая развёртка (Curve_Inverted) start = std::make_pair(true_start, RastriginFunc(true_end, d - y_addition)); end = std::make_pair(true_end, RastriginFunc(true_start, d - y_addition)); } std::pair<float, float> x_Rmax = std::make_pair(start.first, end.first); std::pair<float, float> y_Rmax = std::make_pair(start.second, end.second); Interval initial_interval(start, end, N); float Mmax = initial_interval.M; float m = r * Mmax; R.emplace_back(std::move(initial_interval)); // Локальный лучший — каждый процесс ведёт свой best_f; глобальный обмен лучшим мы сознательно не делаем (дорого). float best_f = end.second; // Основной цикл while (true) { // 1) Глобальная проверка останова по итерациям if (++schetchick == global_iterations) { const Interval& top = R.front(); const float len = top.end.first - top.start.first; Extr.emplace_back(len); Extr.emplace_back(global_iterations); // Сигнал «стоп» всем int my_stop = 1; int any_stop = 0; boost::mpi::all_reduce(world, my_stop, any_stop, boost::mpi::maximum<int>()); break; } // Текущий «лучший» интервал в куче const float x1L = x_Rmax.first; const float x2L = x_Rmax.second; const float y1L = y_Rmax.first; const float y2L = y_Rmax.second; // 2) Шаг поиска по характеристикам const float new_param = Shag(m, x1L, x2L, y1L, y2L, N, r); const PeanoCurve_2D* __restrict p = LocCurve->HitTest_2D(new_param); const float new_x1 = p->x1; const float new_x2 = p->x2; const float new_value = RastriginFunc(new_x1, new_x2); const std::pair<float, float> promejutochnaya_tochka(new_param, new_value); if (new_value < best_f) { best_f = new_value; Extr.emplace_back(best_f); Extr.emplace_back(new_x1); Extr.emplace_back(new_x2); } // 3) Разделение интервала, как у вас std::pop_heap(R.begin(), R.end(), Compare); const Interval promejutochny_otrezok = std::move(R.back()); R.pop_back(); Interval curr (promejutochny_otrezok.start, promejutochnaya_tochka, N); Interval curr1(promejutochnaya_tochka, promejutochny_otrezok.end, N); const float currM = curr1.M > curr.M ? curr1.M : curr.M; const float len2 = promejutochny_otrezok.end.first - new_param; const float len1 = new_param - promejutochny_otrezok.start.first; const size_t r_size = R.size(); if (len2 + len1 == dmax) { dmax = len2 > len1 ? len2 : len1; #pragma loop(ivdep) for (size_t i = 0u; i < r_size; ++i) { const float l = R[i].end.first - R[i].start.first; if (l > dmax) { dmax = l; } } } // 4) Обновление характеристик (адаптивный/неадаптивный режим) — строго по вашему шаблону if (mode) { const float threshold_03 = 0.3f * initial_length; if (threshold_03 > dmax && schetchick % 3u == 0u || 10.0f * dmax < initial_length) { if (currM > Mmax) { Mmax = currM; m = r * Mmax; } const float inv_threshold_03 = 1.0f / threshold_03; const float progress = fmaf(-inv_threshold_03, dmax, 1.0f); const float alpha = fmaf(progress, progress, 1.0f); const float betta = 2.0f - alpha; const float inv_dmax = 1.0f / dmax; const float MULTIPLIER = inv_dmax * Mmax; const float global_coeff = fmaf(MULTIPLIER, r, -MULTIPLIER); const float GLOBAL_FACTOR = betta * global_coeff; curr .ChangeCharacteristic(fmaf(GLOBAL_FACTOR, len1, curr .M * alpha), N); curr1.ChangeCharacteristic(fmaf(GLOBAL_FACTOR, len2, curr1.M * alpha), N); #pragma loop(ivdep) for (size_t i = 0u; i < r_size; ++i) { const float li = R[i].end.first - R[i].start.first; R[i].ChangeCharacteristic(fmaf(GLOBAL_FACTOR, li, R[i].M * alpha), N); } std::make_heap(R.begin(), R.end(), Compare); } else { if (currM > Mmax) { Mmax = currM; m = r * Mmax; curr .ChangeCharacteristic(m, N); curr1.ChangeCharacteristic(m, N); #pragma loop(ivdep) for (size_t i = 0u; i < r_size; ++i) { R[i].ChangeCharacteristic(m, N); } std::make_heap(R.begin(), R.end(), Compare); } else { curr .ChangeCharacteristic(m, N); curr1.ChangeCharacteristic(m, N); } } } else { if (currM > Mmax) { Mmax = currM; m = r * Mmax; curr .ChangeCharacteristic(m, N); curr1.ChangeCharacteristic(m, N); #pragma loop(ivdep) for (size_t i = 0u; i < r_size; ++i) { R[i].ChangeCharacteristic(m, N); } std::make_heap(R.begin(), R.end(), Compare); } else { curr .ChangeCharacteristic(m, N); curr1.ChangeCharacteristic(m, N); } } // 5) Поместить оба подинтервала обратно R.emplace_back(std::move(curr)); std::push_heap(R.begin(), R.end(), Compare); R.emplace_back(std::move(curr1)); std::push_heap(R.begin(), R.end(), Compare); // 6) Потенциальная КРОСС-ИНЪЕКЦИЯ (синхронное общение только здесь) { const float cooling = expf(-schetchick / 200.0f); const uint32_t T = fmaf(20.0f, cooling, 10.0f); const float k = fmaf(0.2f, cooling, 0.7f); // Локальное решение «готов инъектировать?» int do_inject_local = (schetchick % T == 0u && schetchick > T && !R.empty()) ? 1 : 0; int do_inject_all = 0; // Инъекция возможна только при желании ОБОИХ boost::mpi::all_reduce(world, do_inject_local, do_inject_all, boost::mpi::minimum<int>()); if (do_inject_all) { // Собираем данные своей вершины const Interval& topL = R.front(); const PeanoCurve_2D* __restrict p1L = LocCurve->HitTest_2D(topL.start.first); const PeanoCurve_2D* __restrict p2L = LocCurve->HitTest_2D(topL.end.first); CrossMsg outbound { p1L->x1, p1L->x2, p2L->x1, p2L->x2, topL.R }; CrossMsg inbound; // Симметричный двусторонний обмен (без блокировок очередности) boost::mpi::request reqs[2]; reqs[0] = world.isend(partner, /*tag*/ 1, outbound); reqs[1] = world.irecv(partner, /*tag*/ 1, inbound); boost::mpi::wait_all(reqs, reqs + 2); // Маппинг координат партнёра в локальный параметр const float newParam1_remote = LocCurve->FindX_2D(inbound.s_x1, inbound.s_x2); const float newParam2_remote = LocCurve->FindX_2D(inbound.e_x1, inbound.e_x2); // y на концах пересчитываем локально по присланным (x1,x2) — это тот же f() const std::pair<float, float> newStart_remote(newParam1_remote, RastriginFunc(inbound.s_x1, inbound.s_x2)); const std::pair<float, float> newEnd_remote(newParam2_remote, RastriginFunc(inbound.e_x1, inbound.e_x2)); Interval injected(newStart_remote, newEnd_remote, N); injected.R = inbound.Rtop * k; // как в исходнике: масштаб от вершины «донорской» стороны R.emplace_back(std::move(injected)); std::push_heap(R.begin(), R.end(), Compare); } } // 7) Остановка по точности const Interval& top = R.front(); const float interval_length = top.end.first - top.start.first; if (interval_length < epsilon) { Extr.emplace_back(interval_length); Extr.emplace_back(schetchick); int my_stop = 1; int any_stop = 0; boost::mpi::all_reduce(world, my_stop, any_stop, boost::mpi::maximum<int>()); break; } // Обновление «максимального» интервала x_Rmax = std::make_pair(top.start.first, top.end.first); y_Rmax = std::make_pair(top.start.second, top.end.second); // 8) Глобальный флажок останова — если напарник уже остановился (или мы), выходим синхронно { int my_stop = 0; int any_stop = 0; boost::mpi::all_reduce(world, my_stop, any_stop, boost::mpi::maximum<int>()); if (any_stop) { break; } } } return Extr; } // ... конец функции Base_LNA_1_2_Mer_AGP(...)
cpp#include <vector> #include <utility> #include <algorithm> // heap операции #include <boost/mpi.hpp> #include <boost/serialization/access.hpp> #include <boost/serialization/serialization.hpp>
(Больше ничего не требуется: мы используем собственную CrossMsg
со встроенной Boost.Serialization, без экзотических контейнеров.)
Interval
, не меняем порядок вычислений в горячем цикле.R
у каждого процесса изолированы; изменения характеристик (ChangeCharacteristic
) выполняются локально над своими элементами.R
вершины-донора для масштабирования k
.y
для концов «впрыснутого» интервала не шлём, а пересчитываем: это та же точка в , следовательно тот же f
, кэш здесь не страдает (вызов крайне дешёвый).Shag
, разбиение, адаптация m
, поддержка dmax
, логика останова, — неизменны.CrossMsg
и отправлять одним world.isend()
батчем (массив), уменьшая количество обменов.all_reduce
— редкая проверка (раз в K
итераций) и/или неблокирующий обмен флажками (polling iprobe
).R
и буферы под конкретный ранк/поток, использовать reserve
с запасом, избегать реаллокаций; рассмотреть custom‐allocator с 64-байтовым выравниванием.RastriginFunc
вызывает fabe13_cos
, убедиться, что она LTO/inlined; для sincos
блоков — не вызывать их в 2D ветке в горячем цикле (сейчас и так не вызываются).ChangeCharacteristic
— возможно, стоит векторизовать «массовый» проход по куче (строгие alias-квалификаторы у вас уже стоят).xor_rand_*
для этого TU).если захотите — могу дать вариант с асинхронными «почтовыми ящиками» для кросс-инъекций (независимые темпы ранков, без all-reduce на каждом шаге).