循环范围拆分中的变量预评估
variables pre-evaluation in loop range spliting
我想多线程一个for循环,但我的循环中有一些变量需要知道以前的状态。好吧,这并不容易解释。
这是一个示例:
double mu1 = 0, q1 = 0;
double max_sigma = 0, max_val = 0;
for( i = 0; i < N; i++ )
{
double p_i, q2, mu2, sigma;
p_i = h[i]*scale;
mu1 *= q1;
q1 += p_i;
q2 = 1. - q1;
if(std::min(q1,q2) < FLT_EPSILON || std::max(q1,q2) > 1. -FLT_EPSILON )
continue;
mu1 = (mu1 + i*p_i)/q1;
mu2 = (mu - q1*mu1)/q2;
sigma = q1*q2*(mu1 - mu2)*(mu1 - mu2);
if( sigma > max_sigma )
{
max_sigma = sigma;
max_val = i;
}
}
scale
是一个double
标量值。
h
是一个std::vector<std::uint64_t>
如果我在 sevral 部分中拆分范围以进行处理任何子范围,我可以在本地(在每个线程中)首先计算p_i
。
但我不明白我如何确定mu1
的价值.
所以我的问题是:有没有办法确定范围 B 的线程开头的mu1
,而没有事先mu1
范围 A 的线程中处理了什么的结果?如果是,如何?
对于所示的代码,使用多线程解决方案似乎很难实现很多目标。问题在于mu1
和q1
取决于上一个循环的值,因此在上一个循环完成之前,您无法真正继续。
如果你的代码更像是:
for( i = 0; i < N; i++ )
{
SomeComplexAndSlowCalculation(); // Not depending on mu1 and q1
mu1 = mu1 * ....;
q1 = q1 + ....;
SomeOtherComplexAndSlowCalculation(); // Depending on mu1 and q1
// but not changing them
}
您可以使用std::condition_variable
这样的东西:
SomeComplexAndSlowCalculation(); // Not depending on mu1 and q1
cv_previous.wait(...); // wait for thread handling previous index to complete
mu1 = mu1 * ....;
q1 = q1 + ....;
cv_next.notify_one(); // tell thread handling next index to carry on
SomeOtherComplexAndSlowCalculation(); // Depending on mu1 and q1
// but not changing them
您必须为每个索引启动一个新线程。
为了做出任何改变/改进,这两个功能必须非常慢。
我怀疑并行性会导致速度提高,但您实现这一目标的方法是代数减少计算,使其基于 i 的绝对值而不是先前的状态 (i-1),因此例如替换
p_1 = h[i]*scale;
mu1 *= q1;
q1 += p_1;
mu1 = product_n(pre_scaled_h, 0, i-1);
q1 = sum_n(pre_scaled_h, 0, i);
其中 h[] 是预缩放的,以简化对其的操作,并且定义了 product_n 和 sum_n以计算预缩放 h 中的相应乘积和元素的总和,从 0 到相应的第三个参数(包括 0)(请注意,mu1 基于 i-1 而不是 i,因为在重新计算 q1 之前将其乘以 q1)。
这种代数约简将消除对先前迭代的依赖性,并且应该可以用于除 max_sigma 和 max_val 之外的所有变量,这可能必须在每个单独的线程上计算,然后必须比较相应的线程最大值集才能找到真正的最大值。 对这些线程进行传统的锁定可能会消除任何可能的速度提升,因此处理这些需要自己仔细管理线程(因为例如并发::p arallel_for 不能保证哪个工作块将在给定线程上运行)。
请注意,您应该能够将其简化为单个计算而不是迭代循环(当然,在 h 上进行简单的和/乘积运算),因为代数约简似乎完全基于 h[]。 如果可以将其简化为没有迭代循环的单个方程,则您将获得比任何其他选项更高的性能。
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 将数组的地址分配给变量并删除
- 为"adjacent"变量赋值时出现问题
- enum是C++中的宏变量还是整数变量
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 用C++中的一个变量定义一个常量
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 你能重载对象变量名本身返回的内容吗
- 如何改进一堆在已知值范围内评估变量的 else-if 条件?
- 何时枚举变量在C 中评估
- C++ 动态评估变量类型布尔值
- VS 中的 C++ 17 会导致 C++14 中不存在的变量(重新)评估错误
- 我如何评估来自CIN的变量的表达式
- C 变量模板评估指向成员的指针
- 在C 中使用两个CHAR变量评估布尔值
- C++ - 将输入字符串作为内部代码变量进行评估
- 成员变量在评估前未正确更新
- 循环范围拆分中的变量预评估
- 定义(变量)未被 MSVC 正确评估