我正在使用openMP版本,它不支持复杂参数的reduce()。我需要像
这样的快速点积函数std::complex< double > dot_prod( std::complex< double > *v1,std::complex< double > *v2,int dim )
{
std::complex< double > sum=0.;
int i;
# pragma omp parallel shared(sum)
# pragma omp for
for (i=0; i<dim;i++ )
{
#pragma omp critical
{
sum+=std::conj<double>(v1[i])*v2[i];
}
}
return sum;
}
显然,此代码不会加速问题,但会降低速度。如果没有对复杂参数使用reduce(),您是否有快速解决方案?
答案 0 :(得分:4)
每个线程可以计算私有和作为第一步,作为第二步,它可以组成最终总和。在这种情况下,关键部分仅在最后一步中需要。
std::complex< double > dot_prod( std::complex< double > *v1,std::complex< double > *v2,int dim )
{
std::complex< double > sum=0.;
int i;
# pragma omp parallel shared(sum)
{
std::complex< double > priv_sum = 0.;
# pragma omp for
for (i=0; i<dim;i++ )
{
priv_sum += std::conj<double>(v1[i])*v2[i];
}
#pragma omp critical
{
sum += priv_sum;
}
}
return sum;
}
答案 1 :(得分:1)
尝试并行进行乘法运算,然后对它们进行串行求和:
template <typename T>
std::complex<T> dot_prod(std::complex<T> *a, std::complex<T> *b, size_t dim)
{
std::vector<std::complex<T> > prod(dim); // or boost::scoped_array + new[]
#pragma omp parallel for
for (size_t i=0; i<dim; i++)
// I believe you had these reversed
prod[i] = a[i] * std::conj(b[i]);
std::complex<T> sum(0);
for (size_t i=0; i<dim; i++)
sum += prod[i];
return sum;
}
当然,这确实需要O(暗淡)工作记忆。
答案 2 :(得分:0)
为什么不让N个线程计算N个单独的总和。然后在结束时你只需要求N个和,这可以连续完成,因为N非常小。虽然我不知道如何使用OpenMP实现这一目标(目前我没有任何经验),但我确信这很容易实现。