使用 AVX 功能时崩溃

Posted

技术标签:

【中文标题】使用 AVX 功能时崩溃【英文标题】:crashing when I using AVX function 【发布时间】:2018-05-03 08:00:46 【问题描述】:
#include "stdio.h"
#include "math.h"
#include "stdlib.h"
#include "x86intrin.h"

void dd_m(double *clo, int m) 

int j;
__m256d *vclo = (__m256d *)clo;
__m256d al=_mm256_set_pd(0,0,0,0);
__m256d clo_n=_mm256_set_pd(0,0,0,0);
int i;
for (j = 0; j < m; j++) 
    for (i = 0; i < m; i++) 
        al = _mm256_add_pd(vclo[m/4*j+i] , clo_n);
    


int main(int argc, const char * argv[])

int m;
double* zlo;
int i;


m=(int)pow(2,8);

zlo=(double *)_mm_malloc(sizeof(double) * m*m,32);
for (i=0;i<m*m;i++) 
    zlo[i]=0.0;

dd_m(zlo, m);

_mm_free(zlo);

return 0;

这是我的代码。 它会产生错误

“线程 1:EXC_BAD_ACCESS(代码=1,地址=0x102900000)”

在 for 循环内。

我使用最新的 xcode 和 clang。

我该怎么办?

【问题讨论】:

请修正您的格式,并指出故障发生在哪一行。 顺便说一句,值得一读the question on why not to cast the return value of malloc() and family in C。 你应该调试ji的值会出现这个错误,检查是否有超出范围的索引并计算出公式。提示:for (i = 0; i + 3 &lt; m; i++) 如果您希望它真正快速运行,您将需要使用多个累加器来隐藏 FP add 的延迟。在 Skylake 上,vaddpd 有 4 个周期延迟,但每个周期有 2 个吞吐量(与 256 位负载相同),因此您需要同时保持 8 个向量加法在运行中,以成为 ALU / L1d 缓存吞吐量的瓶颈。除非您使用 -ffast-math,否则编译器无法为您展开具有多个累加器的 FP 缩减。 m=(int)pow(2,8); => 1 &lt;&lt; 8 【参考方案1】:

通过将clo 转换为vclo 指向256 位向量,您的行长度除以四,您在索引计算中更改了它,但在i 的内部循环中没有更改。

for (j = 0; j < m; j++) 
    for (i = 0; i < m/4; i++)  // in vclo, the rows are only m/4 long
        al = _mm256_add_pd(vclo[m/4*j+i] , clo_n);
    

【讨论】:

谢谢。但是,似乎只有 2 个 for 循环有效。如果有另一个循环我该怎么办...像那样... for (j = 0; j 画出你的矩阵图,可视化循环嵌套中数据元素的访问方式,以真正理解代码。矩阵的行被分成 4 个双精度数的 SIMD 寄存器。遍历行的每个索引(即在 [...*...+...] 访问中的 + 右侧)只能从 0 变为 (row-length/4 - 1)。如果您遍历具有相同索引的列,即 k,它需要从 0 到 (column-height - 1) 的不同范围。您可能希望使用 clo 并通过强制转换构建一个包含 4 个行元素的 SIMD 寄存器,并通过收集构建一个包含 4 个列元素的 SIMD 寄存器。

以上是关于使用 AVX 功能时崩溃的主要内容,如果未能解决你的问题,请参考以下文章

使用 AVX 后 SSE 运行缓慢 [重复]

使用 Intel Core i7 的 AVX 上的非法指令

使用 AVX2 支持编译并运行

使用多版本控制时的编译时 AVX 检测

_mm_storeu_ps 的 AVX 等效项?

如何处理 SIGSEGV,Segmentation fault。使用 Avx2 时