65

数値のモジュラスを計算することは、少なくとも単純な算術テスト (数値が配列の長さを超えるかどうかを確認するなど) と比較して、多少高価な操作であると思います。これが実際に当てはまる場合、たとえば次のコードを置き換える方が効率的ですか。

res = array[(i + 1) % len];

以下で?:

res = array[(i + 1 == len) ? 0 : i + 1];

前者の方が見やすいですが、後者の方が効率的ではないでしょうか。もしそうなら、コンパイル済み言語が使用されたときに、最適化コンパイラーが最初のスニペットを 2 番目のスニペットに置き換えることを期待できますか?

もちろん、この「最適化」(実際に最適化である場合) がすべての場合に機能するとは限りません (この場合、i+1が を超えない場合にのみ機能しlenます)。

4

8 に答える 8

47

私の一般的なアドバイスは次のとおりです。見やすいと思われるバージョンを使用してから、システム全体をプロファイリングします。プロファイラーがボトルネックとしてフラグを立てるコードの部分のみを最適化します。モジュロ演算子がその中に含まれないことに、最低のお金を賭けます。

特定の例に関する限り、特定のコンパイラを使用して特定のアーキテクチャでどちらが高速かを判断できるのはベンチマークだけです。modulo をbranchingに置き換える可能性がありますが、どちらが速いかは明らかではありません。

于 2013-03-24T07:57:06.660 に答える
30

簡単な測定:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    int test = atoi(argv[1]);
    int divisor = atoi(argv[2]);
    int iterations = atoi(argv[3]);

    int a = 0;

    if (test == 0) {
        for (int i = 0; i < iterations; i++)
            a = (a + 1) % divisor;
    } else if (test == 1) {
        for (int i = 0; i < iterations; i++)
            a = a + 1 == divisor ? 0 : a + 1;
    }

    printf("%d\n", a);
}

gcc または clang を使用してコンパイルし、(モジュロ バージョン) または(比較バージョン) を-O3実行すると、time ./a.out 0 42 1000000000time ./a.out 1 42 1000000000

  • モジュロ バージョンの6.25 秒のユーザー ランタイム、
  • 比較版は1.03秒。

(gcc 5.2.1 または clang 3.6.2 を使用; Intel Core i5-4690K @ 3.50GHz; 64 ビット Linux)

これは、おそらく比較バージョンを使用することをお勧めします。

于 2016-01-31T13:33:47.973 に答える
-3

モジュロは、ほとんどのアーキテクチャ (x86 の DIV など) で単一のプロセッサ命令で実行できます。ただし、必要なものに対する時期尚早の最適化である可能性があります。

于 2013-03-24T08:02:33.513 に答える