Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 矢量化内存比英特尔快内存好吗?_C_X86_Vectorization_Memcpy - Fatal编程技术网

C 矢量化内存比英特尔快内存好吗?

C 矢量化内存比英特尔快内存好吗?,c,x86,vectorization,memcpy,C,X86,Vectorization,Memcpy,我已经实现了一个SSE4.2版本的memcpy,但在Xeon V3上我似乎无法击败_intel_fast_memcpy。我在收集例程中使用我的例程,其中每个位置的数据在4到15字节之间变化。我在这里和英特尔的网站上看过很多帖子,但都不走运。我应该看看什么是好的源代码?你能用16B的加载和存储来进行收集,然后重叠到底有多少垃圾字节吗 // pseudocode: pretend these intrinsics take void* args, not float char *dst = some

我已经实现了一个SSE4.2版本的memcpy,但在Xeon V3上我似乎无法击败_intel_fast_memcpy。我在收集例程中使用我的例程,其中每个位置的数据在4到15字节之间变化。我在这里和英特尔的网站上看过很多帖子,但都不走运。我应该看看什么是好的源代码?

你能用16B的加载和存储来进行收集,然后重叠到底有多少垃圾字节吗

// pseudocode: pretend these intrinsics take void* args, not float
char *dst = something;
__m128 tmp = _mm_loadu_ps(src1);
_mm_storeu_ps(dst, tmp);
dst += src1_size;

tmp = _mm_loadu_ps(src2);
_mm_storeu_ps(dst, tmp);
dst += src2_size;

...
重叠存储非常高效(一级缓存可以很好地吸收它们),现代CPU应该能够很好地处理这一问题。未对齐的货物/商店足够便宜,我认为你无法战胜这一点。(假设页面拆分加载的平均数量。即使缓存线拆分加载的平均数量超过了平均数量,也可能不会有问题。)

这意味着内部循环中没有条件分支来决定复制策略或任何掩码生成或其他操作。您所需要的只是在收集缓冲区的末尾增加一个高达12B的额外数据,以防最后一个副本应该只有4B。(您还需要收集的元素不在页面末尾16B范围内,其中下一页未映射或不可读。)

如果读取要收集的元素的末尾是一个问题,那么对于加载来说,
vpmaskmov
可能是一个好主意。如果您的元素是4B对齐的,那么在末尾之外读取最多3个字节总是可以的。您仍然可以在dst缓冲区中使用正常的16B向量存储


我使用了
\u ps
加载,因为
movups
movupd
movdqu
短1个字节,但执行相同的操作(请参阅,以及tag wiki中的其他链接)。(clang有时甚至会使用
movaps
/
movups
来存储
\u mm\u si128


回复:您的评论:不要使用旧版SSE
maskmovdqu
。最大的问题是,它只能作为一个存储,因此不能帮助您避免读取正在收集的对象之外的内容。它绕过了缓存(它是一个NT存储),这使得重新加载此数据时速度非常慢

AVX版本(和)并非如此,因此将代码转换为使用
maskmovdqu
可能会大大降低速度


相关报道:我不久前发布了一个问答。我得到了一些有趣的回复。显然,这通常不是解决任何问题的最佳方法,尽管我(聪明的IMO)生成面具的策略非常有效

MOVMASKPS在当时是一个非常好的主意,我从来没有用过


我不确定我是否理解为什么你相信你可以击败工程师编写的优化例程,并访问硅片的设计者。还有一个建议:如果你可以将每个位置的所有数据填充到16字节,那么你的memcpy在每个位置都会成为一个固定的16字节副本。无需检查长度或使用未对齐的访问。然后返回给我mcpy:即使是不明显的事情,如分支和分支目标之间的字节数,或者指令对齐,也会影响分支预测和i-cache命中率。准确复制它们的代码,然后开始调整,看看性能下降的地方。我不相信我能打败它,但当我的自定义实现由于数据量很大,所以英特尔的填充将非常昂贵。目前,我使用MaskLoad和MaskStand带有预定义的掩码。因为这些只支持32位操作,所以我必须处理左上角,这就是为什么我的代码是标准的……有很多性能链接,尤其是当你说MaskLoad和MaskSturn时,你是说,不是NT提示的缓慢字节粒度,对吗?