Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.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
Performance 重写memcpy/memcmp/。。。使用SIMD指令有意义吗?_Performance_Sse_Simd - Fatal编程技术网

Performance 重写memcpy/memcmp/。。。使用SIMD指令有意义吗?

Performance 重写memcpy/memcmp/。。。使用SIMD指令有意义吗?,performance,sse,simd,Performance,Sse,Simd,重写memcpy/memcmp/。。。使用SIMD指令在大型软件中有意义吗 如果是这样,为什么默认情况下GCC不为这些库函数生成SIMD指令 此外,SIMD是否可以改进其他功能?是的,使用SSE指令,这些功能要快得多。如果您的运行时库/编译器instrinsic包含优化的版本,那就太好了,但这似乎并不普遍 我有一个定制的SIMDmemchr,它比库版本快得多。特别是当我查找2或3个字符中的第一个字符时(例如,我想知道这行文本中是否有一个等式,我搜索=,\n,\r中的第一个) 另一方面,库函数经过

重写memcpy/memcmp/。。。使用SIMD指令在大型软件中有意义吗

如果是这样,为什么默认情况下GCC不为这些库函数生成SIMD指令


此外,SIMD是否可以改进其他功能?

是的,使用SSE指令,这些功能要快得多。如果您的运行时库/编译器instrinsic包含优化的版本,那就太好了,但这似乎并不普遍

我有一个定制的SIMD
memchr
,它比库版本快得多。特别是当我查找2或3个字符中的第一个字符时(例如,我想知道这行文本中是否有一个等式,我搜索
=
\n
\r
中的第一个)

另一方面,库函数经过了很好的测试,因此只有当您经常调用它们并且分析器显示它们占您CPU时间的很大一部分时,才值得编写自己的库函数。

这可能无关紧要。CPU比内存带宽快得多,编译器运行库提供的
memcpy
等的实现可能已经足够好了。在“大规模”软件中,无论如何,您的性能不会被复制内存所控制(它可能由I/O控制)


为了真正提高内存复制性能,一些系统有一个专门的实现,可用于从内存复制到内存。如果需要大幅提高性能,硬件是实现这一点的途径。

这没有意义。如果编译器能够发出SIMD,那么它应该隐式地为memcpy/memcmp/类似的内部函数发出这些指令

您可能需要明确指示GCC发出SSE操作码,例如
-msse-msse2
;某些GCC默认情况下不启用它们。此外,如果您不告诉GCC进行优化(即,
-o2
),它甚至不会尝试发出快速代码

将SIMD操作码用于这样的内存工作可能会对性能产生巨大影响,因为它们还包括缓存预取和其他DMA提示,这对优化总线访问非常重要。但这并不意味着您需要手动发射它们;尽管大多数编译器一般都会发出SIMD操作,但我使用过的每一个编译器至少都会处理基本CRT内存函数的SIMD操作


将编译器设置为SSE模式也可以使基本数学函数受益匪浅。在basic
sqrt()
上,只需告诉编译器使用SSE操作码而不是糟糕的旧x87 FPU

在x86硬件上,如果处理顺序不正确,这应该没什么大不了的。处理器将实现必要的ILP,并尝试为memcpy每个周期发出最大数量的加载/存储操作,无论是SIMD还是标量指令集memcpy最有可能得到正确优化。来自
的许多其他函数也受益匪浅,并且没有被编译器广泛优化。@BenVoigt:GCC并不总是内联好版本的库函数,但好的库有好的手工编写的asm。e、 g.显示了GCC在
-O1
处内联一个非常糟糕的
repne scasb
strlen
,或在
-O2
处内联一个复杂的每次32位位位黑客,它不利用SSE2的任何优势。该程序完全依赖于strlen的巨大缓冲区的性能,因此调用glibc的优化版本对它来说是一个巨大的胜利。库和内联之间有很大的不同。SIMD memcpy通常只会在源和/或目标已经在缓存中的副本上更快,因为几乎任何半正常的memcpy都应该能够饱和可用的DRAM带宽。@Paul:SIMD总是更好。如果它不是因为内存访问无法跟上而严格地加快速度,那么该内核将被释放,用于超线程、节能或推测性无序执行。正如Crashworks所说,由于预取暗示,SSE将更快地将数据提取到缓存中。如果没有SSE,CPU可能必须在获取数据和执行复制之间交替进行,SSE两者都是并行进行的。在memcpy等人的情况下,执行线程中没有任何其他事情,因此没有任何好处。如果您的内核在等待DRAM访问时被暂停,那么您就无能为力了-DRAM延迟大约为200个时钟,这是一个大量的指令周期,无所事事。@Paul:(1)并不是所有的
memcpy
调用都需要数千个字节。您可能很容易在循环中使用其他处理调用~20字节的
memcpy
。(2) 现代CPU内核并不局限于处理来自单个线程的指令,因此我提到了超线程。(3) 当读预取采用流水线时,DRAM延迟就不那么重要了,只有吞吐量是重要的。(4) 即使DRAM吞吐量使代码步履蹒跚,但还是最好高效地执行复制,因为CPU可以在相同的时间内完成工作,并且功耗更低(例如,动态降低时钟频率)。您使用的是哪种craptastic库没有好的SIMD
memchr
?Glibc已经为i386和x86-64(以及大多数其他ISA)手工编写了asm版本的
memchr
/
strchr
/
memmove
等等,它们非常适合大缓冲区,而且很多都有很好的小缓冲区策略。(通过动态链接器符号解析进行运行时调度,以便使用AV