AVX:数据对齐:store crash,storeu,load,loadu 没有

AVX: data alignment: store crash, storeu, load, loadu doesn't

我正在修改 RNNLM 一个神经网络来研究语言模型。但是考虑到我的语料库的大小,它 运行 真的很慢。我试图优化矩阵*向量例程(这是一个占小数据集总时间 63% 的例程(我预计它在大数据集上会更糟))。现在我坚持使用内在函数。

    for (b=0; b<(to-from)/8; b++) 
    {
        val = _mm256_setzero_ps();
        for (a=from2; a<to2; a++) 
        {
            t1 = _mm256_set1_ps (srcvec.ac[a]);
            t2 = _mm256_load_ps(&(srcmatrix[a+(b*8+from+0)*matrix_width].weight));
            //val =_mm256_fmadd_ps (t1, t2, t3)
            t3 = _mm256_mul_ps(t1,t2);
            val = _mm256_add_ps (val, t3);
        }
        t4 = _mm256_load_ps(&(dest.ac[b*8+from+0]));
        t4 = _mm256_add_ps(t4,val);
        _mm256_store_ps (&(dest.ac[b*8+from+0]), t4);
    }

此示例崩溃于:

_mm256_store_ps (&(dest.ac[b*8+from+0]), t4);

但是如果我改成

_mm256_storeu_ps (&(dest.ac[b*8+from+0]), t4);

(我想你是未对齐的)一切都按预期进行。我的问题是:为什么 load 会工作(而如果数据未对齐,它不应该工作)而存储不会。 (此外两者都在同一个地址上运行)。

dest.ac 已使用

分配
void *_aligned_calloc(size_t nelem, size_t elsize, size_t alignment=64)
{
    size_t max_size = (size_t)-1;

    // Watch out for overflow
    if(elsize == 0 || nelem >= max_size/elsize)
        return NULL;

    size_t size = nelem * elsize;
    void *memory = _mm_malloc(size+64, alignment);
    if(memory != NULL)
        memset(memory, 0, size);
    return memory;
}

并且它至少有 50 个元素长。 (顺便说一句,在 VS2012 中我有一些随机分配的非法指令,所以我使用 linux。)

提前谢谢你, 阿肯图斯

TL:DR:在优化代码中,。商店不会。


您的示例代码不会自行编译,所以我无法轻松检查 _mm256_load_ps 编译成什么指令。

我用 gcc 4.9 做了一个小实验,它根本没有为 _mm256_load_ps 生成 vmovaps,因为我只使用加载的结果作为另一个的输入操作说明。它使用内存操作数生成该指令。 AVX 指令对其内存操作数没有对齐要求。 (越过缓存行会影响性能,越过页面边界会影响性能,但您的代码仍然有效。)

另一方面,商店会生成 vmov... 指令。由于您使用了需要对齐的版本,因此它会在未对齐的地址上出错。只需使用未对齐的版本;当地址对齐时它会一样快,而当它不对齐时它仍然可以工作。

我没有仔细检查您的代码以查看是否所有访问都应该对齐。我假设不是,从你措辞的方式来看,只是问为什么你没有因为未对齐的负载而出现故障。就像我说的,可能你的代码没有编译成任何 vmovaps 加载指令,否则即使 "aligned" AVX 加载也不会在未对齐的地址上出错。

你 运行 AVX(没有 AVX2 或 FMA?)在 Sandy/Ivybridge CPU 上吗?我认为这就是为什么您的 FMA 内在函数被注释掉的原因。