c++ - 一个 SSE Stdlib 式的库?

标签 c++ c visual-c++ assembly sse

通常,我在“网上”遇到的与 SSE/MMX 相关的所有内容都是作为 vector 和矩阵的数学内容出现的。但是,我正在寻找 SSE 优化的“标准函数”库,例如 Agner Fog 提供的库,或 GCC 中一些基于 SSE 的字符串扫描算法。

作为一个快速的总体纲要:这些将是 memset、memcpy、strstr、memcmp BSR/BSF 之类的东西,即从 SSE 指令构建的 stdlib-esque

我更希望它们使用内在函数而不是汇编用于 SSE1(正式的 MMX2),但两者都可以。希望这不是太广泛的范围。

更新 1

经过一番搜索,我发现了一些有前途的东西,一个图书馆引起了我的注意:

  • LibFreeVec :似乎仅适用于 mac/IBM(由于基于 AltiVec),因此用处不大(对我而言),而且我似乎找不到直接下载链接,也没有说明支持的最低 SSE 版本

  • 我还在一些向量化的字符串函数(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 汇编变体在我的家用机器上排名第二,在 intel 系统上排名第二(但结果看起来有点不一致,一个拥抱阻止了它主导了 SSE1 版本)。 MSVC memcpy 赢得了英特尔系统测试的手,这是由于 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 esque 类型库。似乎这些项目中的大多数都致力于特定的小部分(问题)。

    这就提出了一个问题,那么创建一个开源的,可能是多平台性能的 crt/stdlib 项目,创建标准化函数的各种版本,每个版本都针对特定情况进行优化以及“最佳情况”是否值得? '/函数的一般使用变体,带有标量/MMX/SSE/SSE2+ (à la MSVC) 的运行时分支或强制编译时标量/SIMD 开关。

    这对于 HPC 或对每一点性能都很重要的项目(如游戏)很有用,让程序员无需担心内置函数的速度,只需要进行少量调整即可找到最佳优化变体。

    更新 4

    我认为应该扩展这个问题的性质,包括可以使用 SSE/MMX 来优化非 vector/矩阵应用程序的技术,这也可能用于 32/64 位标量代码。一个很好的例子是如何使用标量技术(位操作)、MMX 和 SSE/SIMD 一次检查给定 32/64/128/256 位数据类型中字节的出现

    另外,我看到很多关于“只使用 ICC”的答案,这是一个很好的答案,这不是我的答案,因为首先,ICC 不是我可以连续使用的东西(除非英特尔有免费的学生版)对于 Windows),由于 30 次试用。其次,更贴切的是,我不仅关注库本身,而且关注用于优化/创建它们包含的函数的技术,以进行我个人的启发和改进,因此我可以将这些技术和原则应用于我自己的代码(在需要时),结合使用这些库。希望能澄清那部分:)

    最佳答案

    这是一篇关于如何使用 SIMD 指令来矢量化字符计数的文章:

    http://porg.es/blog/ridiculous-utf-8-character-counting

    关于c++ - 一个 SSE Stdlib 式的库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3862587/

    相关文章:

    c++ - 使用 Eclipse : How to add include paths and libraries for all your C/C++ project

    c++ - 如何将参数传递给 C++ 应用程序

    c - 为什么我的程序不返回文本文件的最大和最小整数?

    c++ - 如何释放字符串未使用的容量

    c++ - 在 Visual Studio 中创建静态/动态 C++ 库时出现问题

    c++ - MATLAB 因 calllib(C++ .h 文件和 FORTRAN .dll)而崩溃

    c++ - GMock : How to return a fuction pointer defined by an EXPECT_CALL()

    c - 如何在 C 中声明指向结构的指针数组然后使用它?

    c - 为什么在C程序中变量被突变?

    c++ - MSVC : Embedding Data in Program