【发布时间】:2020-04-30 07:49:49
【问题描述】:
void new2d(int* aInit, int* aResult)
{
int cyclic[34] = {0};
for (int i = 0; i < 32; i++)
{
cyclic[i] = aInit[i];
}
cyclic[32] = aInit[0];
cyclic[33] = aInit[1];
float three = 3.0;
for (int i = 0; i < 32; i += 4)
{
int j = i + 1;
int k = j + 1;
__asm__ __volatile__
(
"vmovdqa (%0), %%xmm0;"
"vmovdqa (%1), %%xmm1;"
"vcvtdq2ps %%xmm0, %%xmm0;"
"vcvtdq2ps %%xmm1, %%xmm1;"
"addps %%xmm0, %%xmm1;"
"vmovdqa (%2), %%xmm1;"
"vcvtdq2ps %%xmm1, %%xmm1;"
"addps %%xmm0, %%xmm1;"
"vbroadcastss (%3), %%xmm1;"
"divps %%xmm0, %%xmm1;"
"vcvtps2dq %%xmm0, %%xmm0;"
"vmovdqa %%xmm0, (%4);"
:
: "a"(&(cyclic[i])), "b"(&(cyclic[j])), "c"(&(cyclic[k])), "d"(&three), "S"(&aResult[i])
);
}
}
尝试将一个初始数组的三个子数组相加,找到它们的均值,并将它们保存在结果数组中。虽然,在启动 .exe 文件后,它显示分段错误。 我该如何解决?使用 GNU 2.9.3,Ubuntu
【问题讨论】:
-
请注意,您的内联程序集无效,因为它没有声明适当的clobbers。使用内部函数可以更好地完成此类任务。
-
即使你安全地使用内联汇编,你也会因为许多错过的优化而自责,例如将
3.0的负载提升出循环,并乘以1.0/3而不是使用慢除法。还为vcvtdq2ps使用内存源操作数。如果您的整数不会溢出,请执行整数加法,而不是转换为 FP 并返回。此外,j的负载cyclic[i+1 + 0..3]可以通过像vpalignr来自cyclic[i]向量和下一次迭代的cyclic[i]向量的随机播放来生成。未对齐的负载吞吐量通常非常好,所以可能不值得 -
如果你使用了内在函数,编译器可以为你做一些这样的事情,例如将
vbroadcastss(_mm_set1_ps(3.0f)) 吊出循环。
标签: c++ assembly x86-64 simd inline-assembly