AVX:数据对齐:存储崩溃,存储,加载,加载并不是

时间:2015-05-19 14:59:10

标签: c++ avx

我正在修改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);

(我认为你的未对齐)一切都按预期工作。我的问题是:为什么加载工作(如果数据未对齐则不应该如此)并且存储不会。 (此外两者都在同一地址上运行)。

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个元素。 (BTW和VS2012我在一些随机分配上有非法指令,所以我使用linux。)

提前谢谢你, Arkantus。

1 个答案:

答案 0 :(得分:1)

TL:DR :在优化代码loads will fold into memory operands for other operations, which don't have alignment requirements in AVX中。商店赢了。

您的示例代码本身并不编译,因此我无法轻松检查_mm256_load_ps编译的指令。

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

另一方面,商店确实会生成vmov...指令。由于您使用了对齐所需的版本,因此它在未对齐的地址上出现故障。只需使用未对齐版本;当地址对齐时,它会一样快,并且在没有地址时仍能正常工作。

我没有仔细检查您的代码,看看是否应该对齐所有访问。我假设没有,从你用它的方式来解释为什么你也没有因未对齐的载荷而出错。就像我说的,可能你的代码没有编译成任何vmovaps加载指令,或者甚至&#34;对齐&#34; AVX在未对齐的地址上加载了故障。

您是否在Sandy / Ivybridge CPU上运行AVX(没有AVX2或FMA?)?我认为这就是为什么你的FMA教义被注释掉了。