C++ 循环范围拆分中的变量预评估
我想对for循环进行多线程处理,但我的循环中有一些变量需要知道之前的状态。 这不太容易解释 以下是一个例子:C++ 循环范围拆分中的变量预评估,c++,multithreading,c++11,C++,Multithreading,C++11,我想对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; q
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;
}
}
double mu1=0,q1=0;
双最大值σ=0,最大值=0;
对于(i=0;i1.-FLT_ε)
继续;
mu1=(mu1+i*p_i)/q1;
mu2=(mu-q1*mu1)/q2;
西格玛=q1*q2*(mu1-mu2)*(mu1-mu2);
如果(西格玛>最大西格玛)
{
最大西格玛=西格玛;
max_val=i;
}
}
scale
是一个double
标量值
h
是一个std::vector
如果我将范围分成几个部分来处理任何子范围,我可以首先在本地(每个线程中)计算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
}
您必须为每个索引启动一个新线程
这两个函数的运行速度必须非常慢。对于所显示的代码,使用多线程解决方案似乎很难实现。问题是
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
}
您必须为每个索引启动一个新线程
要使其产生任何差异/改进,这两个函数必须非常慢。我怀疑并行性是否会导致速度提高,但实现这一点的方法是以代数方式减少计算量,使其基于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[]被预缩放以简化对其的操作,而乘积n和总和n被定义为计算预缩放h中元素的相应乘积和总和,从0到相应的第三个参数(请注意,mu1基于i-1而不是i,因为在重新计算q1之前,它被乘以q1)
这种代数化简将消除对上一次迭代的依赖性,并且除了max_sigma和max_val之外,所有变量都应该是可能的,这可能必须在每个单独的线程上进行计算,然后必须比较对应的线程最大值集,以找到真正的最大值。对这些线程的传统锁定可能会消除任何可能的速度提升,因此需要自己仔细管理线程的处理(因为例如concurrency::parallel_for不能保证在给定线程上运行哪个工作块)
请注意,您应该能够将其简化为单个计算,而不是迭代循环(当然,对h进行简单的和/积运算),因为代数简化似乎完全基于h[]。如果您可以将其简化为一个方程,而无需迭代循环,那么您将获得比任何其他选项更高的性能。我怀疑并行性是否会导致速度的提高,但您实现这一点的方法是以代数方式将计算量减少到基于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[]被预缩放以简化对其的操作,而乘积n和总和n被定义为计算预缩放h中元素的相应乘积和总和,从0到相应的第三个参数(请注意,mu1基于i-1而不是i,因为在重新计算q1之前,它被乘以q1)
这种代数化简将消除对上一次迭代的依赖性,并且除了max_sigma和max_val之外,所有变量都应该是可能的,这可能必须在每个单独的线程上进行计算,然后必须比较对应的线程最大值集,以找到真正的最大值。对这些线程的传统锁定可能会消除任何可能的速度提升,因此需要自己仔细管理线程的处理(因为例如concurrency::parallel_for不能保证在给定线程上运行哪个工作块)
请注意,您应该能够将其简化为单个计算,而不是迭代循环(当然,对h进行简单的和/积运算),因为代数简化似乎完全基于h[]。如果您可以在不使用迭代循环的情况下将其简化为单个等式,那么您将获得比任何其他选项都高的性能。多线程循环的目标是什么?如果要提高性能,您可能最好将重点放在循环的自动矢量化上,因为管理线程的开销可能会抵消这种相对简单的算法跨多个内核运行的任何好处。还要注意的是,除了mu1(以及mu2计算中使用的未定义的mu?,max_sigma和max_val)之外,还需要进行特殊处理,以避免线程之间出现争用情况。您好,Matt。我甚至知道如何自己对循环进行矢量化。我想知道,在这种情况下,是否有一种有效的多线程处理方法。。。如果元素
i
的计算在某种程度上依赖于元素i-1