“私有变量不能被还原”,尽管该变量是在SIMD块之外定义的
问题描述:
我有一个使用OpenMP的C++项目,我尝试使用Blue Gene/Q上的LLVM进行编译。还有一个功能,剥离下来的,看起来是这样的:“私有变量不能被还原”,尽管该变量是在SIMD块之外定义的
template <typename FT, int veclen>
inline void xmyNorm2Spinor(FT *res,
FT *x,
FT *y,
double &n2res,
int n,
int n_cores,
int n_simt,
int n_blas_simt) {
#if defined(__GNUG__) && !defined(__INTEL_COMPILER)
double norm2res __attribute__((aligned(QPHIX_LLC_CACHE_ALIGN))) = 0;
#else
__declspec(align(QPHIX_LLC_CACHE_ALIGN)) double norm2res = 0;
#endif
#pragma omp parallel shared(norm_array)
{
// […]
if (smtid < n_blas_simt) {
// […]
double lnorm = 0;
//#pragma prefetch x,y,res
//#pragma vector aligned(x,y,res)
#pragma omp simd aligned(res, x, y : veclen) reduction(+ : lnorm)
for (int i = low; i < hi; i++) {
res[i] = x[i] - y[i];
double tmpd = (double)res[i];
lnorm += (tmpd * tmpd);
}
// […]
}
}
// […]
}
的错误是这样就在这里:
In file included from /homec/hbn28/hbn28e/Sources/qphix/tests/timeDslashNoQDP.cc:6:
In file included from /homec/hbn28/hbn28e/Sources/qphix/include/qphix/blas.h:8:
/homec/hbn28/hbn28e/Sources/qphix/include/qphix/blas_c.h:156:54: error: private variable cannot be reduction
#pragma omp simd aligned(res,x,y:veclen) reduction(+:lnorm)
^
/homec/hbn28/hbn28e/Sources/qphix/include/qphix/blas_c.h:151:12: note: predetermined as private
double lnorm=0;
^
由于外omp parallel
块,变量lnorm
为每个线程定义。然后有一个额外的SIMD部分,每个线程使用一个SIMD通道。减少应该在线程内完成,所以变量的范围看起来是正确的。尽管如此,编译器并不需要它。
这里有什么问题?
答
的问题似乎是,通过与OpenMP的reduction()
条款上它的参数变量规定的要求omp parallel
块冲突连接到lnorm
变量私人属性(即使lnorm
不是私人相对于reduction()
子句适用的嵌套omp simd
块)。
您可以尝试通过提取lnorm
计算代码到它自己的功能,解决该问题:
template <typename FT, int veclen>
inline double compute_res_and_lnorm(FT *res,
FT *x,
FT *y,
int low,
int hi)
{
double lnorm = 0;
#pragma omp simd aligned(res, x, y : veclen) reduction(+ : lnorm)
for (int i = low; i < hi; i++) {
res[i] = x[i] - y[i];
double tmpd = (double)res[i];
lnorm += (tmpd * tmpd);
}
return lnorm;
}
template <typename FT, int veclen>
inline void xmyNorm2Spinor(FT *res,
FT *x,
FT *y,
double &n2res,
int n,
int n_cores,
int n_simt,
int n_blas_simt) {
#if defined(__GNUG__) && !defined(__INTEL_COMPILER)
double norm2res __attribute__((aligned(QPHIX_LLC_CACHE_ALIGN))) = 0;
#else
__declspec(align(QPHIX_LLC_CACHE_ALIGN)) double norm2res = 0;
#endif
#pragma omp parallel shared(norm_array)
{
// […]
if (smtid < n_blas_simt) {
// […]
double lnorm = compute_res_and_lnorm(res, x, y, low, hi);
// […]
}
}
// […]
}