2

左回転命令にパフォーマンス依存のプログラムがあります。

MSVC では、左回転のターゲットとして _rotl() 組み込み関数を定義するだけで、かなりうまく機能します。

Linux 用の GCC でもうまく動作します。ここでは、同等のソフトウェア構造を定義するだけで十分ですrotl32(x,r) = ((x << r) | (x >> (32 - r)))。コンパイラは、これが 32 ビットの左回転であることを認識し、それを組み込みの同等のものに自動的に置き換えるほど賢いです (公平を期すために、MSVC もそのような検出を行うことができます)。

MinGW の下では、それほど多くはありません。これは、MinGW がコアで GCC を使用しているため、さらに興味深いものです。MinGW は、Windows の組み込み関数をコンパイルできますが_rotl、対応する組み込み関数を明らかにトリガーすることはありません。ソフトウェアのバージョンも検出されていないようですが、公平を期すために、_rotl. 最終結果はパフォーマンスが 10 分の 1 に低下するため、これは間違いなく重要です。

注:テスト済みの MinGW の GCC バージョンは 4.6.2 です。

4

2 に答える 2

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 に答える