我正在用C语言编写OpenCL基准测试。目前,它使用C代码测量CL设备和系统处理器的融合乘累加性能。然后交叉检查结果的准确性。
我编写了本机代码以利用GCC的自动矢量化程序,并且可以正常工作。但是,我注意到GCC带有“ -march = native”标志的某些奇怪行为。
这是我的循环:
#define BUFFER_SIZE_SQRT 4096
#define SQUARE(n) (n * n)
#define ROUNDS_PER_ITERATION 48
static float* cpu_result_matrix(const float* a, const float* b, const float* c)
{
float* res = aligned_alloc(16, SQUARE(BUFFER_SIZE_SQRT) * sizeof(float));
const unsigned buff_size = SQUARE(BUFFER_SIZE_SQRT);
const unsigned round_cnt = ROUNDS_PER_ITERATION;
float lres;
for(unsigned i = 0; i < buff_size; i++)
{
lres = 0;
for(unsigned j = 0; j < round_cnt; j++)
{
lres += a[i] * ((b[i] * c[i]) + b[i]);
lres += b[i] * ((c[i] * a[i]) + c[i]);
lres += c[i] * ((a[i] * b[i]) + a[i]);
}
res[i] = lres;
}
return res;
}
当我在Broadwell系统上使用“ -march = native -Ofast”进行编译时,会得到漂亮的矢量化AVX代码。
.L19:
vmovups ymm0, YMMWORD PTR [rcx+rdx]
mov eax, 48
vmovups ymm2, YMMWORD PTR [rdi+rdx]
vaddps ymm1, ymm0, ymm5
vmovups ymm3, YMMWORD PTR [rsi+rdx]
vaddps ymm4, ymm2, ymm5
vmulps ymm1, ymm1, ymm2
vfmadd132ps ymm4, ymm1, ymm0
vaddps ymm1, ymm3, ymm5
vmulps ymm0, ymm2, ymm0
vmulps ymm0, ymm0, ymm1
vfmadd132ps ymm4, ymm0, ymm3
vmovaps ymm1, ymm4
vxorps xmm0, xmm0, xmm0
.p2align 4,,10
.p2align 3
即使体系结构支持,在桩驱动程序系统上使用相同的标志进行编译也会发出SSE2指令,但不会发出AVX指令。(我在这里澄清我的标题的方式是说Broadwell和打桩机没有什么相似之处,但是它们都支持相似的矢量指令集扩展,因此发出的代码应该相似。)
.L19:
mov eax, 48
movups xmm0, XMMWORD PTR [rcx+rdx]
movups xmm2, XMMWORD PTR [r13+0+rdx]
movaps xmm4, xmm0
movaps xmm1, xmm2
movups xmm3, XMMWORD PTR [rsi+rdx]
addps xmm4, xmm5
addps xmm1, xmm5
mulps xmm4, xmm2
mulps xmm1, xmm0
mulps xmm0, xmm2
addps xmm1, xmm4
movaps xmm4, xmm1
mulps xmm4, xmm3
addps xmm3, xmm5
mulps xmm0, xmm3
addps xmm4, xmm0
pxor xmm0, xmm0
movaps xmm1, xmm4
.p2align 4,,10
.p2align 3
我什至可以使用-march = broadwell编译整个项目,然后在打桩机系统上运行它,并且可以正常工作,并获得约100%的性能提升。
我正在使用GCC 5.1.0进行编译,“-ftree-vectorizer-verbose”似乎不再起作用,因此编译器的行为非常不透明。我尚未找到有关已弃用该标志的任何信息,所以我不确定为什么它不再起作用了,我真的很想弄清楚GCC在做什么。
整个项目在这里:https : //github.com/jakogut/clperf/tree/v0.1
由于整个AMD Bulldozer系列产品无法有效处理256位AVX指令,因此已禁用了AVX。在内部,执行单元只有128位宽。因此,将256位操作拆分为128位,因此没有任何好处。
为了增加侮辱性伤害,在Pipedriver上,256位存储中存在一个错误,该错误将吞吐量降低到每17个周期约1个。
您的测试用例似乎是异常的。在该关键循环中您没有256位存储-这样可以避免该错误。从理论上讲,这使SSE与打桩机的AVX保持一致。
决胜局来自打桩机支持的FMA3指令。这可能就是为什么AVX循环在桩驱动器上确实变得更快的原因。
您可以尝试的一件事就是-mfma4
-mtune=bdver2
看看会发生什么。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句