有没有一种方法可以优化方程中的参数替换,以加快 C++ 中的计算速度

问题描述 投票:0回答:1

我有一组方程,它们采用向量输入并返回不同时间步长的解。方程中有一些参数是在运行时接收的,并在该周期内保持不变。我想用运行时计算的值替换此类参数,以便进一步计算使用带有参数替换值的方程。原始问题有 4000 个这样的参数,但我给出了一个示例方程来说明我想要实现的目标。 一个较小的例子来说明这个问题:

 rval[0]  = -p1*x + p2*y*z;
  rval[1]  = -rval[0] - p3*y*y - dy;
  rval[0] -=  dx;
  rval[2]  =  x + y + z - 1;

{p1,p2,p3} 是一组固定参数,其值是在线接收的,新的方程组本质上将变为

  rval[0]  = (-0.04)*x + (1.0e4)*y*z;
  rval[1]  = -rval[0] - (3.0e7)*y*y - dy;
  rval[0] -=  dx;
  rval[2]  =  x + y + z - 1;

我尝试过的一种方法是使用 symengine 符号 C++ 库,但它增加了使用 symengine 方程的替换和计算的开销 使用 symengine 库尝试了上述方程的代码

// Create a map for substitution
SymEngine::map_basic_basic subs_map;
subs_map[x_sym] = real_double(x);
subs_map[y_sym] = real_double(y);
subs_map[z_sym] = real_double(z);
subs_map[dx_sym] = real_double(dx);
subs_map[dy_sym] = real_double(dy);
subs_map[dz_sym] = real_double(dz);

// Evaluate equations
rval[0] = SymEngine::eval_double(*resv1->subs(subs_map));
rval[1] = SymEngine::eval_double(*resv2->subs(subs_map));
rval[2] = SymEngine::eval_double(*resv3->subs(subs_map));

方程 resv1、resv2 和 resv3 与上述方程相同,但参数被替换 是否有其他方法可以通过替换参数来实现高速评估方程,或者是否有更快的方法在 symengine 中实现此目的。 注意:请注意,我使用的方程组比这个大得多,每个时间步运行多次迭代,但我正在尝试使用较小的方程组来检查解决方案的可行性。

c++ optimization equation solver symengine
1个回答
0
投票

使用

double p2 = 1.0e4
或常数
1.0e4
对于浮点数学单元来说确实没有多大关系。 如果您使用
-ffast-math
,它可能会产生一些影响,因为它可以让编译器重新排序浮点表达式,使其不完全匹配 IEEE 所需的结果,而是生成代数等效的方程。

请参阅 gcc 的 ffast-math 实际上是做什么的?,了解

-ffast-math
的作用和替代方案的详细信息。

即使使用

ffast-math
,真正的常量(即,使用硬编码的常量重新编译程序)可能会在某些情况下导致重大重写(即,它解决了你的常量意味着某个值乘以0,因此它跳过计算值),但如果没有这个值,你就不会得到太大的改进。 如果要求人类连续几百万次乘以 3 乘以 10 到 7,人类可能会变得更快,但 FPU 不会。 百万分之一的乘法也会同样快。

您可以安排数学运算以使 FPU 更快,但这主要涉及使您的数学遵循 SIMD 模式,每个周期执行 4 或 8 或更多并行浮点运算;或者在更极端的情况下,安排您的代码在 GPU 上运行(它可以像超宽 SIMD FPU 一样工作,非常便宜地并行执行 100 个相同的操作)。

这些看起来都不像“修复一些参数”后会神奇地发生的事情。 他们需要您的工作才能开始工作。

© www.soinside.com 2019 - 2024. All rights reserved.