首页 文章

除法和乘法与位移的差异

提问于
浏览
1

免责声明

我想 not 想知道我的代码中的 when or if to use 移位运算符,我感兴趣的是 why 乘法比向左移位更快,而除法则不然 .


当我四处闲逛时,我遇到了关于分割和位移的效率和速度的问题 . 它基本上表明,虽然在2的幂上执行位移时可能会节省几秒钟,但是不必担心一些差异 .

对此我很感兴趣,我决定检查C#中的位移实际上有多快,并意识到一些奇怪的事情:

正如我预期的那样,位移而不是分频更快,但“正常”乘法方法比位移更快 .

我的问题很简单:为什么两位数的乘法比位移更快,尽管位移是处理器的基本操作?


以下是我的测试用例的结果:

Division: | Multiplication:
Bit shift:   315ms   |   315ms
   normal:   406ms   |   261ms

时间是100个案例的平均值,每个案例包括10000个随机正数的每个数字10个操作,范围从1到 int.MaxValue . 操作范围从分割/乘以2到1024(以2的幂为单位)和从1到10位的位移 .


编辑

@usr:我使用的是.NET 4.5.1版

我更新了我的结果,因为我意识到我只计算了我说过的数字的十分之一... facepalm

我的主要:

static Main(string[] args)
{
    Fill(); // fills the array with random numbers
    Profile("division shift:", 100, BitShiftDiv);
    Profile("division:", 100, Div);
    Profile("multiplication shift:", 100, BitShiftMul);
    Profile("multiplication:", 100, Mul);
    Console.ReadKey();
}

这是我的分析方法:

static void Profile(string description, int iterations, Action func)
{
    GC.Collect()
    GC.WaitForPendingFinalizers();
    GC.Collect();

    func();

    Stopwatch stopWatch = Stopwatch.StartNew();
    for (int i = 0; i < iterations; i++)
    {
        func();
    }
    stopWatch.Stop();

    Console.WriteLine(description);
    Console.WriteLine("total: {0}ms", stopWatch.Elapsed.TotalMilliseconds);
    Console.WriteLine("  avg: {0}ms", stopWatch.Elapsed.TotalMilliseconds / (double)iterations);
}

包含操作的Actions的结构如下:

static void <Name>()
{
    for (int s = 1; s <= 10; s++)    /* for shifts */
    for (int s = 2; s <= 1024; s++)  /* for others */ 
    {
        for (int i = 0; i < nums.Length; i++)
        {
            var useless = nums[i] <shift> s;    /* shifting  */
            var useless = nums[i] <operator> s; /* otherwise */
        }
    }
}

nums 是包含 10000000 int 的公共数组,由 Fill() 方法填充 .

1 回答

  • 0

    总结评论中已经提到的答案:

    • 乘法以及位移更快,因为CPU也是 native operation . 它需要一个周期,而位移大约需要四个,这就是它更快的原因 . 分部需要11到18个周期 .

    • 使用C#我无法接近CPU以获得诊断结果,因为在我的代码和CPU之间进行了许多优化 .

    • 此外,微基准测试很难并且可能产生错误的结果,这也可能由于上述原因而发生 .

    如果我忘了什么,请评论并告诉我!

相关问题