2

我有一个程序,它依赖于左旋转指令的性能。

在 MSVC 下,它工作得相当好,只需将 _rotl() 内部函数定义为向左旋转的目标。

在 GCC for Linux 下,它也运行良好。在这里定义等效的软件构造就足够了rotl32(x,r) = ((x << r) | (x >> (32 - r))),编译器足够聪明地识别出这是一个 32 位左循环,并自动将其替换为其内在等效项(公平地说,MSVC 也能够进行这种检测)。

在 MinGW 下,没有那么多。当 MinGW 使用 GCC 作为其核心时,这一点就更加有趣了。MinGW 可以编译 windows 内在函数_rotl,但不会明显触发相应的内在函数。该软件版本似乎也未被检测到,但公平地说,它仍然比_rotl. 最终结果是性能降低了 10 倍,因此这绝对是显着的。

注意:测试 MinGW 的 GCC 版本是 4.6.2

4

2 回答 2

3

以防万一您在 Windows 上遇到了内在函数,这里有一种在 x86 上使用内联汇编器的方法;

uint32_t rotl32_2(uint32_t x, uint8_t r) {
  asm("roll %1,%0" : "+r" (x) : "c" (r));
  return x;
}

在 Ubuntu 的 gcc 上测试过,但应该在 mingw 上运行良好。

于 2013-06-01T12:02:36.780 回答
2

只需包含intrin.h标题。

它是特定于 Windows 的标头,因此如果您正在开发跨平台软件,请不要忘记使用以下条件包装它:

#ifdef _WIN32
# include <intrin.h>
#endif

基准

Run on (4 X 3310 MHz CPU s)
09/07/16 23:29:35
Benchmark                    Time           CPU Iterations
----------------------------------------------------------
BM_rotl/8                   19 ns         18 ns   37392923
BM_rotl/64                 156 ns        149 ns    4487151
BM_rotl/512               1148 ns       1144 ns     641022
BM_rotl/4k                9286 ns       9178 ns      74786
BM_rotl/32k              71575 ns      69535 ns       8974
BM_rotl/256k            583148 ns     577204 ns       1000
BM_rotl/2M             4769689 ns    4830999 ns        155
BM_rotl/8M            19997537 ns   18720120 ns         35
BM_rotl_intrin/8             6 ns          6 ns  112178768
BM_rotl_intrin/64           55 ns         53 ns   14022346
BM_rotl_intrin/512         431 ns        407 ns    1725827
BM_rotl_intrin/4k         3327 ns       3338 ns     224358
BM_rotl_intrin/32k       27093 ns      26596 ns      26395
BM_rotl_intrin/256k     217633 ns     214167 ns       3205
BM_rotl_intrin/2M      1885492 ns    1853925 ns        345
BM_rotl_intrin/8M      8015337 ns    7626716 ns         90

基准代码

#include <benchmark/benchmark.h>

#define MAKE_ROTL_BENCHMARK(name) \
  static void name(benchmark::State& state) { \
    auto arr = new uint32_t[state.range(0)]; \
    while (state.KeepRunning()) { \
      for (int i = 0; i < state.range(0); ++i) { \
        arr[i] = _rotl(arr[i], 16); \
      } \
    } \
    delete [] arr; \
  } \
  /**/

MAKE_ROTL_BENCHMARK(BM_rotl)
#include <intrin.h>
MAKE_ROTL_BENCHMARK(BM_rotl_intrin)

#undef MAKE_ROTL_BENCHMARK

BENCHMARK(BM_rotl)->Range(8, 8<<20);
BENCHMARK(BM_rotl_intrin)->Range(8, 8<<20);

BENCHMARK_MAIN()
于 2016-09-07T20:56:46.890 回答