为什么我的C语言向量乘法程序这么慢?

为什么我的C语言向量乘法程序这么慢?,c,x86,sse,simd,avx,C,X86,Sse,Simd,Avx,我正试图找到一种最有效的方法,用C语言将两个2dim数组(单精度)相乘,并从一个天真的想法开始,通过遵循算术规则来实现它: for (i = 0; i < n; i++) { sum += a[i] * b[i]; } 一定是出了什么问题,但我找不到它-因此任何提示都将不胜感激。如果您的编译器支持OpenMP 4.0或更高版本,我将使用它来请求编译器对原始循环进行矢量化(如果使用足够高的优化级别,它可能已经这样做了;但是OpenMP允许您提供有关对齐等方面的提示,以改进结果)。与AVX内

我正试图找到一种最有效的方法,用C语言将两个2dim数组(单精度)相乘,并从一个天真的想法开始,通过遵循算术规则来实现它:

for (i = 0; i < n; i++) {
sum += a[i] * b[i]; }

一定是出了什么问题,但我找不到它-因此任何提示都将不胜感激。

如果您的编译器支持OpenMP 4.0或更高版本,我将使用它来请求编译器对原始循环进行矢量化(如果使用足够高的优化级别,它可能已经这样做了;但是OpenMP允许您提供有关对齐等方面的提示,以改进结果)。与AVX内部函数相比,它的优势在于,它可以在其他架构(如ARM)或其他x86 SIMD指令集上工作(假设您告诉编译器以它们为目标)只需简单的重新编译,而无需重写代码:

float sum = 0.0f;
#pragma omp simd reduction(+:sum) 
for (i = 0; i < n; i++) {
    sum += a[i] * b[i];
}
float sum=0.0f;
#pragma omp simd缩减(+:总和)
对于(i=0;i
众所周知,水平加法指令的速度并不特别快。因此,按向量累加通常是有帮助的,例如
sum=\umm256\u add\ps(sum,res\mult)
并且只有在循环完成时才执行一次hadd。这些天,我可能会使用OpenMP SIMD pragma使用原始循环明确请求编译器对其进行矢量化(如果在检查程序集时编译器还没有这样做;可能需要调整优化选项)您的文本显示“两个2dim数组”但是,您的代码看起来像是在计算两个一维向量的一点积。您应该澄清这个问题。如果要将两个二维数组相乘,则缓存问题是一个巨大的因素。相关:显示编译器如何向量化和展开(如果您让他们通过
-ffast math
假装FP math是关联的)。在末尾执行一次SIMD水平求和,而不是在内部循环中!!但是如果您实际上有矩阵,那么您对输出的每个元素都执行行*列点积,那么您可能不希望单独执行这些操作,即使您对其中一个元素进行了转置,这样一个元素中的行和另一个元素中的列在内存中是连续的。请参见,和yo你可以查看编译器生成的asm,看看它是如何矢量化的。(希望至少有4个矢量累加器,最好是8个。)非常感谢大家:我将尝试omp simd pragma以及任何其他提示。老实说,我已经(成功地)做到了40多年来,我一直不知道这匹老马是否会学会新把戏……:-)但我担心,除非深入研究,否则我不会进一步讨论这个主题。注意:我只是使用omp simd pragma编译,但不幸的是,没有重大区别。@MarioH您记得在启用OpenMP支持的情况下编译吗?您是否检查了编译器是否已经对循环进行了矢量化?gcc和clang都在循环结束时生成了一个有效的简化步骤。此外,gcc使用单个累加器向量,这会阻止利用ILP。底线是,如果你想要你的代码快,你应该自己写。
float sum = 0.0f;
#pragma omp simd reduction(+:sum) 
for (i = 0; i < n; i++) {
    sum += a[i] * b[i];
}