如何优化阀门仿真逻辑?

时间:2019-05-01 12:49:08

标签: c opencl sse simd differential-equations

这是我为自己创建的一个简单的逻辑编程和优化练习法,偶然发现了它。

我有一个简单方案的数值模拟。考虑一些储液器(或电容器)Cm,该储液器经常随着压力而上升。让我们将其当前状态称为Vm

enter image description here

根据以下逻辑,它的输出端有一个可以打开或关闭的阀或闸G

  • 门打开,当压力(或电压)Vm超过某个阈值时,将其命名为VopenVm > Vopen
  • 门保持打开状态,而当前爆发Ia大于某些IholdIa > IHold
  • 门仅从水库中传导功率(就像二极管一样)

我正在对此进行数值ODE求解,即在每个(相等,较小)的时间步dt处确定VmIa。有以下三种变体:


变量类型:

float Vm=0.0, Ia=0.0, Vopen, Ihold, Ra, dt;
int G=0;

循环主体v1(序列):

Vm = Vm + (-Ia*G)*dt;
G |= (Vm > Vopen);
Ia = Ia + (Vm*Ra*G)*dt;
G &= (Ia > Ihold);

循环主体v2(串行,带有temp var,三进制条件):

int Gv; // temporary var
Vm = Vm + (-Ia*G)*dt;
Gv = (Vm > Vopen) ? 1 : G; 
Ia = Ia + (Vm*Ra*Gv)*dt;
G = (Ia > Ihold) ? Gv : 0;

循环主体v3(并行,带缓存):

// cache new state first
float Vm1 = Vm + (-Ia*G)*dt;
float Ia1 = Ia + (Vm*Ra*G)*dt;
// update memory
G = ( Vm1 > Vopen ) || (( Ia1 > Ihold ) && G);
Vm = Vm1;
Ia = Ia1; // not nesesary to cache, done for readibility

G来自建立下面的真值表,加上想象力: enter image description here


问:

  • 哪个是正确的?是吗?
  • 第三个变体(并行逻辑)与前两个(串行逻辑)有何不同?
  • 有没有更有效的方法来执行这种逻辑?

PS。我正在尝试针对SSE优化它,然后(单独)针对OpenCL(如果有优化提示)

PPS。对于那些好奇的人,这里是my working simulator,涉及此门(html / js)

1 个答案:

答案 0 :(得分:1)

  1. 从整体上讲,它们是相同的,应该都能满足您的需求。

  2. 您的序列号将产生半步。这意味着,如果将其分解为离散描述,则V(t)可以描述为I(t)之前的1/2 dt。第一个将使G在每个半步中变化,第二个将G与I同步。但是由于您不评估中间的G并不重要。 V也没有真正的问题,我相距半步,但您应牢记,但也许应该使用矢量{V(t),(I(t-1)+ I(t ))/ 2,G(t)}。

    并行代码将使它们全部处于同一时间步。

  3. 对于纯线性问题,直接积分是一个很好的解决方案。高阶ode求解器不会为您买任何东西。纯线性系统的状态空间表示仅以不同的方式编写相同的直接积分。

对于SIMD优化,无需做任何准备。您需要逐步评估,因为您要按V更新I和按I更新V。这意味着您无法并行运行这些步骤,这使得不可能进行许多有趣的优化。