【发布时间】:2013-06-26 21:45:39
【问题描述】:
我正在开发一个包含大量 SIMD 内在代码的代码库。现在我们有了 AVX2,我们仍然需要在不支持 AVX2 的处理器上运行 SIMD 代码,这将大大增加工作量。再加上 AVX2 shuffle 的 128 位车道交叉限制也使事情变得复杂。由于这些原因,现在是更多依赖自动矢量化的好时机。让我害怕的主要事情是一个简单的更改会破坏并行性的前景,以及在出现问题时调试自动矢量化代码的前景。
我已经用 g++ -O1 -g -ftree-vectorize 编译了以下内容并尝试使用 GDB 逐步完成(有谁知道为什么 -ftree-vectorize 不适用于 -O0 ?)
float a[1000], b[1000], c[1000];
int main(int argc, char **argv)
{
for (int i = 0; i < argc; ++i)
c[i] = a[i] + b[i];
return 0;
}
但没有得到任何有意义的结果。例如,有时 i 的值表示
似乎主要问题是很难将 SIMD 状态映射到原始 C 状态以进行调试。但实际上,能做到吗?
【问题讨论】:
-
为什么要调试它?如果您想验证它是否被矢量化,检查汇编代码或运行基准测试(在完全优化设置下)不是更好吗?如果您想查找错误,请调试非矢量化(以及其他非优化)版本。
-
是的,编译器错误在发生时非常糟糕。我不知道(源代码级别)调试器是否是处理它的正确工具,但无论如何,我理解。
-
因此,到目前为止的错误调试大多是假设性的。我绝对记得在 Visual C++ 2010 矢量化程序中提交了一个错误,该错误导致它不正确地将未对齐的负载与算术指令融合到单个 x86 指令中,导致它在未对齐的数组上运行时崩溃。
-
我更感兴趣的是了解向量化代码的效率,这对于汇编代码来说是非常困难的。当生成多个版本的代码时,情况会变得更糟(一些用于处理 SIMD 余数或未对齐部分,一些用于处理别名数组等)。如果我可以一次遍历 GDB 4、8 或 16 中的循环,并并排查看相应的汇编代码,那可能有助于理解。实际上,我真正想要的是一个源到源编译器,它可以用向量类型和运算符重写你的代码。有这种事吗?
-
使用 gcc,
-fdump-tree-optimized生成一个具有类似 C 语法的文件,显示执行了哪些优化。
标签: c++ vectorization sse simd avx2