【发布时间】:2014-11-20 09:35:31
【问题描述】:
我不明白为什么这样的代码没有用 gcc 4.4.6 向量化
int MyFunc(const float *pfTab, float *pfResult, int iSize, int iIndex)
{
for (int i = 0; i < iSize; i++)
pfResult[i] = pfResult[i] + pfTab[iIndex];
}
note: not vectorized: unhandled data-ref
但是,如果我写下面的代码
int MyFunc(const float *pfTab, float *pfResult, int iSize, int iIndex)
{
float fTab = pfTab[iIndex];
for (int i = 0; i < iSize; i++)
pfResult[i] = pfResult[i] + fTab;
}
gcc 成功自动向量化这个循环
如果我添加 omp 指令
int MyFunc(const float *pfTab, float *pfResult, int iSize, int iIndex)
{
float fTab = pfTab[iIndex];
#pragma omp parallel for
for (int i = 0; i < iSize; i++)
pfResult[i] = pfResult[i] + fTab;
}
我有以下错误未矢量化:未处理的数据参考
你能帮我解释一下为什么第一个代码和第三个代码不是自动矢量化的吗?
第二个问题: 数学操作数似乎没有向量化(exp、log 等...),例如此代码
for (int i = 0; i < iSize; i++)
pfResult[i] = exp(pfResult[i]);
未矢量化。是因为我的 gcc 版本?
编辑: 使用新版本的 gcc 4.8.1 和 openMP 2011 (echo |cpp -fopenmp -dM |grep -i open) 对于所有类型的循环,我基本上都有以下错误
for (iGID = 0; iGID < iSize; iGID++)
{
pfResult[iGID] = fValue;
}
note: not consecutive access *_144 = 5.0e-1;
note: Failed to SLP the basic block.
note: not vectorized: failed to find SLP opportunities in basic block.
编辑2:
#include<stdio.h>
#include<sys/time.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <omp.h>
int main()
{
int szGlobalWorkSize = 131072;
int iGID = 0;
int j = 0;
omp_set_dynamic(0);
// warmup
#if WARMUP
#pragma omp parallel
{
#pragma omp master
{
printf("%d threads\n", omp_get_num_threads());
}
}
#endif
printf("Pagesize=%d\n", getpagesize());
float *pfResult = (float *)malloc(szGlobalWorkSize * 100* sizeof(float));
float fValue = 0.5f;
struct timeval tim;
gettimeofday(&tim, NULL);
double tLaunch1=tim.tv_sec+(tim.tv_usec/1000000.0);
double time = omp_get_wtime();
int iChunk = getpagesize();
int iSize = ((int)szGlobalWorkSize * 100) / iChunk;
//#pragma omp parallel for
for (iGID = 0; iGID < iSize; iGID++)
{
pfResult[iGID] = fValue;
}
time = omp_get_wtime() - time;
gettimeofday(&tim, NULL);
double tLaunch2=tim.tv_sec+(tim.tv_usec/1000000.0);
printf("%.6lf Time1\n", tLaunch2-tLaunch1);
printf("%.6lf Time2\n", time);
}
结果
#define _OPENMP 201107
gcc (GCC) 4.8.2 20140120 (Red Hat 4.8.2-15)
gcc -march=native -fopenmp -O3 -ftree-vectorizer-verbose=2 test.c -lm
很多
note: Failed to SLP the basic block.
note: not vectorized: failed to find SLP opportunities in basic block.
and note: not consecutive access *_144 = 5.0e-1;
谢谢
【问题讨论】:
-
第一件事确实是尝试更新版本的 gcc。然后意识到没有
restrict向量化可能是错误的。并添加 -ffast-math ,否则编译器会害怕。对于 exp 和 log,我确定我已经看到了有关 SO 的相关问题。基本上,您需要一个库来提供 exp 和 log 的矢量版本,以便 gcc 可以生成对它们的调用。 -
暂别我之前的评论,你为什么不在循环中使用
i??? -
非常感谢我已经尝试过使用 'restrict' 和 const,结果是一样的跨度>
-
我已经安装了 gcc 4.8.1,现在我的所有循环都提供了以下信息说明:无法 SLP 基本块。注意:未矢量化:未能在基本块中找到 SLP 机会。
-
您的代码无法编译(缺少标头?),这很粗鲁。如果您想在不安装任何东西的情况下测试代码,可以使用在线编译器。
标签: gcc openmp auto-vectorization