我正在修改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。
答案 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教义被注释掉了。