通常,我遇到的与SSE/MMX有关的“网上”所有内容都是作为 vector 和矩阵的数学知识而出现的。但是,我正在寻找SSE优化的“标准函数”的库,例如Agner Fog提供的库或GCC中某些基于SSE的字符串扫描算法。
作为一般的简要介绍:这些将是诸如memset,memcpy,strstr,memcmp BSR/BSF之类的东西,即基于SSE插入构建的stdlib风格
我最好希望它们用于使用内在函数而不是汇编函数的SSE1(以前为MMX2),但是两者都很好。希望这不会太广泛。
更新1
经过一番搜索,我发现了一些很有前途的东西,一个图书馆引起了我的注意:
我还遇到了一些矢量化字符串函数(strlen,strstr strcmp)上的an article。但是SSE4.2超出了我的能力范围(如前所述,我想坚持使用SSE1/MMX)。
更新2
Paul R激励我做一些基准测试,不幸的是,由于我的SSE汇编编码经验接近zip,因此我使用了别人的(http://www.mindcontrol.org/~hplus/)基准测试代码并将其添加到其中。所有测试(不包括原始测试,即VC6 SP5)都是在VC9 SP1下编译的,具有完整/自定义优化功能,并启用了
/arch:SSE
。第一个测试是我的家用计算机(AMD Sempron 2200+ 512mb DDR 333),其上限为SSE1(因此,没有通过MSVC memcpy进行矢量化处理):
comparing P-III SIMD copytest (blocksize 4096) to memcpy
calculated CPU speed: 1494.0 MHz
size SSE Cycles thru-sse memcpy Cycles thru-memcpy asm Cycles thru-asm
1 kB 2879 506.75 MB/s 4132 353.08 MB/s 2655 549.51 MB/s
2 kB 4877 598.29 MB/s 7041 414.41 MB/s 5179 563.41 MB/s
4 kB 8890 656.44 MB/s 13123 444.70 MB/s 9832 593.55 MB/s
8 kB 17413 670.28 MB/s 25128 464.48 MB/s 19403 601.53 MB/s
16 kB 34569 675.26 MB/s 48227 484.02 MB/s 38303 609.43 MB/s
32 kB 68992 676.69 MB/s 95582 488.44 MB/s 75969 614.54 MB/s
64 kB 138637 673.50 MB/s 195012 478.80 MB/s 151716 615.44 MB/s
128 kB 277678 672.52 MB/s 400484 466.30 MB/s 304670 612.94 MB/s
256 kB 565227 660.78 MB/s 906572 411.98 MB/s 618394 603.97 MB/s
512 kB 1142478 653.82 MB/s 1936657 385.70 MB/s 1380146 541.23 MB/s
1024 kB 2268244 658.64 MB/s 3989323 374.49 MB/s 2917758 512.02 MB/s
2048 kB 4556890 655.69 MB/s 8299992 359.99 MB/s 6166871 484.51 MB/s
4096 kB 9307132 642.07 MB/s 16873183 354.16 MB/s 12531689 476.86 MB/s
full tests
第二次测试是在大学工作站上完成的(Intel E6550、2.33Ghz,2gb DDR2 800?)
VC9 SSE/memcpy/ASM:
comparing P-III SIMD copytest (blocksize 4096) to memcpy
calculated CPU speed: 2327.2 MHz
size SSE Cycles thru-sse memcpy Cycles thru-memcpy asm Cycles thru-asm
1 kB 392 5797.69 MB/s 434 5236.63 MB/s 420 5411.18 MB/s
2 kB 882 5153.51 MB/s 707 6429.13 MB/s 714 6366.10 MB/s
4 kB 2044 4447.55 MB/s 1218 7463.70 MB/s 1218 7463.70 MB/s
8 kB 3941 4613.44 MB/s 2170 8378.60 MB/s 2303 7894.73 MB/s
16 kB 7791 4667.33 MB/s 4130 8804.63 MB/s 4410 8245.61 MB/s
32 kB 15470 4701.12 MB/s 7959 9137.61 MB/s 8708 8351.66 MB/s
64 kB 30716 4735.40 MB/s 15638 9301.22 MB/s 17458 8331.57 MB/s
128 kB 61019 4767.45 MB/s 31136 9343.05 MB/s 35259 8250.52 MB/s
256 kB 122164 4762.53 MB/s 62307 9337.80 MB/s 72688 8004.21 MB/s
512 kB 246302 4724.36 MB/s 129577 8980.15 MB/s 142709 8153.80 MB/s
1024 kB 502572 4630.66 MB/s 332941 6989.95 MB/s 290528 8010.38 MB/s
2048 kB 1105076 4211.91 MB/s 1384908 3360.86 MB/s 662172 7029.11 MB/s
4096 kB 2815589 3306.22 MB/s 4342289 2143.79 MB/s 2172961 4284.00 MB/s
full tests
可以看出,SSE在我的家庭系统上非常快,但是落在intel机器上(可能是由于编码错误?)。我的x86装配体变体在家用计算机中排名第二,在英特尔系统中排名第二(但是结果看起来有点不一致,一个拥抱阻止它在SSE1版本中占主导地位)。 MSVC memcpy赢得了intel系统测试的成功,这是由于SSE2向量化,尽管在我的家用计算机上,它失败了,甚至可怕的
__movsd
也击败了它。陷阱:内存全部对齐2的幂。(希望)刷新了缓存。 rdtsc用于计时。
兴趣点:MSVC具有(未在任何引用文献中列出)__movsd内部函数,它输出与我正在使用的相同的汇编代码,但是却失败(即使是内联!)。这可能就是为什么其未上市。
可以强制VC9 memcpy在我的非sse 2机器上进行矢量化,但是它将破坏FPU堆栈,它似乎也有错误。
这是我用来测试的full source(再次包括我的更改,请记入http://www.mindcontrol.org/~hplus/作为原始内容)。可根据要求提供项目文件的二进制文件。
总之,似乎与MSVC crt类似,切换变体可能是最好的,只有更多选项和单次过帐检查(通过内联函数指针?)或更坚固的东西(如内部直接调用)才能使坚固性更强补丁),但是内联可能必须使用最佳情况下的方法
更新3
Eshan提出的一个问题提醒了一些有用且与此相关的问题,尽管仅对位集和位操作BitMagic有用,但对于大位集非常有用,它甚至在SSE2 (bit) optimization上有一篇不错的文章。不幸的是,这仍然不是CRT/stdlib风格的类型库。这些项目中的大多数似乎都专门针对(问题)的一小部分。
这就提出了一个问题,那就是是否值得创建一个开源的,可能是多平台的性能crt/stdlib项目,创建各种版本的标准化功能,每个版本都针对特定情况以及“最佳情况”进行了优化。 '/函数的通用用法变体,具有标量/MMX/SSE/SSE2 +(称为MSVC)的运行时分支或强制编译时标量/SIMD三明治。
这对于HPC或每个性能都至关重要的项目(例如游戏)很有用,从而使程序员不必担心内置功能的速度,只需要进行少量调整即可找到最佳的优化版本。
更新4
我认为应该扩展此问题的性质,以包括可以使用SSE/MMX应用于非 vector/矩阵应用程序优化的技术,这也可能适用于32/64位标量代码。一个很好的例子是如何使用标量技术(位操作),MMX和SSE/SIMD一次检查给定的32/64/128/256位数据类型中的字节是否存在
另外,我看到了很多“仅使用ICC”的答案,那是一个很好的答案,这不是我的答案,因为首先,ICC不是我可以连续使用的东西(除非Intel有免费的学生版) (适用于Windows),由于30次试用。其次,更重要的是,我不仅关注库本身,还关注用于优化/创建它们所包含功能的技术,以进行个人化和改进,因此我可以将此类技术和原理应用于自己的代码中(如果需要),并结合使用这些库。希望可以清除那部分:)
最佳答案
这是有关如何使用SIMD指令向量化字符计数的文章:
http://porg.es/blog/ridiculous-utf-8-character-counting