【问题标题】:Speed difference when using different values with modulo使用带模数的不同值时的速度差异
【发布时间】:2013-01-08 20:20:34
【问题描述】:

我正在使用 gcc 4.6.3 并创建大量随机短裤。我使用以下语句生成它们:

val = SHRT_MAX; //as defined by limits.h
while(array<end) {
    *array++ = rand() % val;
}

这是一个相当快的操作,即使对于多达 5,000,000 个元素的数组也几乎可以立即完成。我对数字变化较小的排序效率感到好奇,并将其更改为:

val = 3;

这造成了相当大的速度差异,它的运行速度比原始语句慢得多。是什么导致了如此大的速度差异?

【问题讨论】:

  • 两个词:编译器优化。有些模数比其他模数更容易修改。
  • 注解,取一个均匀分布的随机数的模并不一定会产生一个范围内的均匀分布的随机数。
  • @honk - 您能否对此进行扩展(或链接到解释)?我不明白为什么会这样。
  • @GordonBailey:这几乎是关于此处随机数的常见问题解答。有关详细说明,请参阅eternallyconfuzzled.com/arts/jsw_art_rand.aspxstackoverflow.com/questions/2509679/… 是这里的答案。

标签: c++ c gcc


【解决方案1】:

SHRT_MAX 很可能大于或等于RAND_MAX。声明:

*array++ = rand() % val;

可以优化成:

int rand_value= rand();
if (rand_value==RAND_MAX) rand_value= 0;
*array++= rand_value;

这更快,因为它用分支替换了模数。第二个版本(val 为 3)无法优化为不带模数的更简单版本。

% SHRT_MAX 不能简化为按位运算。但是结合如何指定rand() 的知识,编译器当然可以优化处理rand() 和大于或等于RAND_MAX 的值的语句。

【讨论】:

    【解决方案2】:

    编译器可以优化模数 (a%B) 的计算,其中 B 是一个常数。它用更简单的算术运算代替了实际的模数。详细信息在 Most optimized way to calculate modulus in C 等主题中进行了解释。但是,对于某些 B 值,此类优化比其他值更快。

    即使是 CPU 除法/取模指令也可能需要不同数量的周期完成(至少在某些 CPU 上)。在此处查看 x86 的编号:http://gmplib.org/~tege/x86-timing.pdf

    【讨论】:

      【解决方案3】:

      SHRT_MAX 是一个2^n-1 值,可以针对除法进行优化。除以 3 要困难得多,因此编译器很可能会决定除以 3(或执行一些其他比 2^n-1 变体慢的魔术操作。

      您可以使用的最快模数是2^n,它可以用单个and-instruction 替换,对于正值:x % 256x &amp; 255 相同。不幸的是,当值可能是负数时,就不是那么容易了……

      【讨论】:

      • 3 也是2^n - 1 (n = 2)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-24
      • 1970-01-01
      • 2012-05-27
      • 1970-01-01
      • 1970-01-01
      • 2011-05-22
      相关资源
      最近更新 更多