为什么 64 位比 32 位更快?

2024-02-12

我一直在进行一些性能测试,主要是为了了解迭代器和简单 for 循环之间的区别。作为其中的一部分,我创建了一组简单的测试,然后对结果感到非常惊讶。对于某些方法,64 位比 32 位快近 10 倍。

我正在寻找的是对为什么会发生这种情况的一些解释。

[下面的答案指出这是由于 32 位应用程序中的 64 位算术造成的。将长整型更改为整数会在 32 和 64 位系统上带来良好的性能。]

这是有问题的 3 种方法。

private static long ForSumArray(long[] array)
{
    var result = 0L;
    for (var i = 0L; i < array.LongLength; i++)
    {
        result += array[i];
    }
    return result;
}

private static long ForSumArray2(long[] array)
{
    var length = array.LongLength;
    var result = 0L;
    for (var i = 0L; i < length; i++)
    {
        result += array[i];
    }
    return result;
}

private static long IterSumArray(long[] array)
{
    var result = 0L;
    foreach (var entry in array)
    {
        result += entry;
    }
    return result;
}

我有一个简单的测试工具来测试这个

var repeat = 10000;

var arrayLength = 100000;
var array = new long[arrayLength];
for (var i = 0; i < arrayLength; i++)
{
    array[i] = i;
}

Console.WriteLine("For: {0}", AverageRunTime(repeat, () => ForSumArray(array)));

repeat = 100000;
Console.WriteLine("For2: {0}", AverageRunTime(repeat, () => ForSumArray2(array)));
Console.WriteLine("Iter: {0}", AverageRunTime(repeat, () => IterSumArray(array)));

private static TimeSpan AverageRunTime(int count, Action method)
{
    var stopwatch = new Stopwatch();
    stopwatch.Start();
    for (var i = 0; i < count; i++)
    {
        method();
    }
    stopwatch.Stop();
    var average = stopwatch.Elapsed.Ticks / count;
    return new TimeSpan(average);
}

当我运行这些时,我得到以下结果:
32 bit:


For: 00:00:00.0006080
For2: 00:00:00.0005694
Iter: 00:00:00.0001717  

64 bit


For: 00:00:00.0007421
For2: 00:00:00.0000814
Iter: 00:00:00.0000818  

我从中读到的内容是使用 LongLength 很慢。如果我使用 array.Length,第一个 for 循环的性能在 64 位中相当不错,但在 32 位中则不然。

我从中读到的另一件事是,迭代数组与 for 循环一样高效,并且代码更干净、更易于阅读!


x64 处理器包含 64 位通用寄存器,可以使用这些寄存器在单个指令中计算 64 位整数的运算。 32位处理器没有这个。这与您的程序特别相关,因为它大量使用long(64 位整数)变量。

例如,在 x64 汇编中,要添加存储在寄存器中的几个 64 位整数,您可以简单地执行以下操作:

; adds rbx to rax
add rax, rbx

要在 32 位 x86 处理器上执行相同的操作,您必须使用两个寄存器,并在第二个操作中手动使用第一个操作的进位:

; adds ecx:ebx to edx:eax
add eax, ebx
adc edx, ecx

更多的指令和更少的寄存器意味着更多的时钟周期、内存读取……这最终会导致性能下降。在数字处理应用程序中,差异非常显着。

对于 .NET 应用程序,64 位 JIT 编译器似乎会执行更积极的优化,从而提高整体性能。

关于您关于数组迭代的观点,C# 编译器足够聪明,可以识别foreach对数组进行特殊处理。生成的代码与使用for循环,建议您使用foreach如果不需要更改循环中的数组元素。除此之外,运行时还可以识别该模式for (int i = 0; i < a.Length; ++i)并省略循环内数组访问的边界检查。这不会发生在LongLength情况下会导致性能下降(32 位和 64 位情况);因为你将使用long变量与LongLength,32 位性能会进一步下降。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 64 位比 32 位更快? 的相关文章

随机推荐

  • 复制功能如何工作? [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我不明白如何copy函数基于文档工作 copy 内置函数将元素从源切片复制到 目标切片 作为一种特殊情况 它还会从 字符串到字节切片 源和目
  • 如何在上传到服务器之前调整/压缩 Android 中的相机图像或图库图像?

    我必须上传可以从图库中选择或用相机拍摄的图像 我已经成功地做到了这一点 但问题是 有时图像大小为 1MB 所以上传到服务器需要更多时间 我需要在上传之前调整此图像的大小 这个怎么做 public void onActivityResult
  • 从 JSON 创建数组的数组

    我在 ajax 调用后收到以下内容response在 PHP 中使用json encode 2013 02 24 0 2013 02 25 0 2013 02 26 1 2013 02 27 6 2013 02 28 6 2013 03 0
  • 无法在cygwin上安装uwsgi

    我的主要操作系统是 Windows 10 但我使用 cygwin 作为终端 通过安装uwsgi时pip3 install uwsgi命令 它失败并显示错误消息 AttributeError module os has no attribut
  • 我如何全局安装 sbt 插件

    我从github下载了android sdk plugin 文档说我需要全局安装插件 将插件全局安装到 sbt plugins 或 sbt 0 13 plugins 分别适用于 0 12 和 0 13 addSbtPlugin com ha
  • 实体(空)不符合键“title”的键值编码

    我正在尝试让 RestKit 和 CoreData 一起工作 我越来越接近了 但我收到以下错误 CoreData error Failed to call designated initializer on NSManagedObject
  • 单个应用程序中的多个 RCTRootView

    我正在创建一个 React Native 应用程序 但我需要使用 Objective C 来构建我的自定义 UIView 但问题是这个 UIView 需要显示反应内容 例如反应文本输入和按钮 我正在考虑向自定义 UIView 添加 RCTR
  • 位图.保存“一般错误”

    当我运行我的应用程序时 出现以下错误 GDI 中发生一般错误 我环顾四周 发现人们也有类似的错误 但没有找到真正的解决方案 或者实施起来确实很痛苦 那些没有得到解决方案的人还没有发布他们的代码 所以我想我不妨尝试一下并提出另一个关于如何修复
  • @login_required 正在丢失当前指定的语言

    我在用i18n patterns使我的应用程序国际化并且它正在工作 除非我单击需要登录的链接 受保护的视图 login required装饰器 我被重定向到默认语言的登录表单 而不是当前活动的语言 如何保留活动 URL 换句话说 当在法语部
  • rawQuery(查询,选择参数)

    我想使用选择查询从表中检索数据 我已经发现 rawQuery query selectionArgs 的方法SQLiteDatabase类来检索数据 但我不知道如何query and selectionArgs应该传递给rawQuery m
  • 你能从 sklearn 网格搜索 (GridSearchCV) 中获得所有估计器吗?

    我最近使用测试了许多超参数组合sklearn model selection GridSearchCV 我想知道是否有一种方法可以调用在此过程中接受过培训的所有先前估算器 search GridSearchCV estimator my e
  • 分布式缓存

    我正在 opensuse linux 上使用 hadoop 19 我没有使用任何集群 而是在我的机器本身上运行我的 hadoop 代码 我遵循放入分布式缓存的标准技术 但我不是一次又一次地从分布式缓存访问文件 而是将文件的内容存储在一个数组
  • 如何知道 C 函数 free 是否正常工作?

    我发现以下代码的结果存在一些差异 include
  • 为什么Java中没有AtomicBoolean数组数据类型?

    我注意到有NOJava 中的 AtomicBooleanArray 数据类型类似于 AtomicIntegerArray 虽然我可以使用 AtomicBoolean 来满足当前的需求 但我很想了解为什么 AtomicBooleanArray
  • 如何在 JavaScript 中记录返回

    我正在为浏览器应用程序的工作项目编写自己的库 并且在决定如何注释代码时遇到同样的老问题 我正在尝试遵循JsDoc https code google com p jsdoc toolkit w list语法 但可能会继续谷歌闭包编译器 ht
  • 仅使用 CSS 交叉淡入淡出多个背景图像 - 单页面设计

    我正在使用多个 div 构建一个响应式单页网站 这些 div 可缩放到用户浏览器的高度和宽度 我想让多个背景图像在网站上的一个 div 内无限循环地交叉淡入淡出 我尝试按照本教程进行操作 http css3 bradshawenterpri
  • 从 Android Activity 绑定到服务

    我有一个启动服务的活动 当活动关闭时 我希望服务继续在后台运行 我在这里有几个问题 关闭活动屏幕会导致活动实际停止吗 还是我需要强行阻止它才能停止 如果关闭屏幕确实导致它停止 那么我认为我需要使用startService开始它 那是对的吗
  • 如何禁用 bootstrap-datetimepicker-master 中的特定日期?

    datepicker datetimepicker format MM dd hh ii P startDate 2016 08 19 10 00 daysOfWeekDisabled 1 2 3 4 5 autoclose true 如何
  • WSDL 中的 有什么区别?

    Both
  • 为什么 64 位比 32 位更快?

    我一直在进行一些性能测试 主要是为了了解迭代器和简单 for 循环之间的区别 作为其中的一部分 我创建了一组简单的测试 然后对结果感到非常惊讶 对于某些方法 64 位比 32 位快近 10 倍 我正在寻找的是对为什么会发生这种情况的一些解释