位对齐可提高空间和性能

2024-01-02

在书里游戏编码完成,第三版, https://rads.stackoverflow.com/amzn/click/com/1584506806作者提到了一种减少数据结构大小的技术and提高访问性能。本质上,它依赖于当成员变量内存对齐时获得性能的事实。这是编译器可以利用的明显的潜在优化,但通过确保每个变量对齐,最终会导致数据结构的大小膨胀。

或者至少这是他的说法。

他表示,真正的性能提升是通过使用你的大脑并确保你的结构经过正确设计,以利用速度的提高,同时防止编译器膨胀。他提供了以下代码片段:

#pragma pack( push, 1 )

struct SlowStruct
{
    char c;
    __int64 a;
    int b;
    char d;
};

struct FastStruct
{
    __int64 a;
    int b;
    char c;
    char d;  
    char unused[ 2 ]; // fill to 8-byte boundary for array use
};

#pragma pack( pop )

使用上面的struct在一项未指定的测试中,他报告的对象性能提高了15.6% (222ms相比192ms)和较小的尺寸FastStruct。这对我来说在纸面上是有意义的,但在我的测试中却站不住脚:

同一时间结果and尺寸(计算char unused[ 2 ])!

现在如果#pragma pack( push, 1 )仅孤立于FastStruct(或完全删除)我们确实看到了差异:

所以,最后,这里存在一个问题:现代编译器(特别是 VS2010)是否已经针对位对齐进行了优化,因此缺乏性能提升(但增加了结构大小作为副作用,如 Mike Mcshaffry 所说)?或者我的测试不够密集/不确定,无法返回任何显着的结果?

对于测试,我在未对齐的矩阵上执行了各种任务,包括数学运算、列主多维数组遍历/检查、矩阵运算等__int64成员。对于这两种结构,它们都没有产生不同的结果。

最后,即使性能没有提高,这仍然是一个需要记住的有用的技巧,可以将内存使用量保持在最低限度。但如果有我没有看到的性能提升(无论多么微小),我会很高兴。


它高度依赖于硬件。

让我演示一下:

#pragma pack( push, 1 )

struct SlowStruct
{
    char c;
    __int64 a;
    int b;
    char d;
};

struct FastStruct
{
    __int64 a;
    int b;
    char c;
    char d;  
    char unused[ 2 ]; // fill to 8-byte boundary for array use
};

#pragma pack( pop )

int main (void){

    int x = 1000;
    int iterations = 10000000;

    SlowStruct *slow = new SlowStruct[x];
    FastStruct *fast = new FastStruct[x];



    //  Warm the cache.
    memset(slow,0,x * sizeof(SlowStruct));
    clock_t time0 = clock();
    for (int c = 0; c < iterations; c++){
        for (int i = 0; i < x; i++){
            slow[i].a += c;
        }
    }
    clock_t time1 = clock();
    cout << "slow = " << (double)(time1 - time0) / CLOCKS_PER_SEC << endl;
    
    //  Warm the cache.
    memset(fast,0,x * sizeof(FastStruct));
    time1 = clock();
    for (int c = 0; c < iterations; c++){
        for (int i = 0; i < x; i++){
            fast[i].a += c;
        }
    }
    clock_t time2 = clock();
    cout << "fast = " << (double)(time2 - time1) / CLOCKS_PER_SEC << endl;



    //  Print to avoid Dead Code Elimination
    __int64 sum = 0;
    for (int c = 0; c < x; c++){
        sum += slow[c].a;
        sum += fast[c].a;
    }
    cout << "sum = " << sum << endl;


    return 0;
}

酷睿 i7 920 @ 3.5 GHz

slow = 4.578
fast = 4.434
sum = 99999990000000000

好吧,差别不大。但在多次运行中它仍然保持一致。
因此,对齐方式在 Nehalem Core i7 上产生了微小的差异。


英特尔至强 X5482 Harpertown @ 3.2 GHz(Core 2 - 代 Xeon)

slow = 22.803
fast = 3.669
sum = 99999990000000000

现在看一下...

6.2 倍快!!!


结论:

您会看到结果。您可以决定是否值得花时间进行这些优化。


EDIT :

相同的基准,但没有#pragma pack:

酷睿 i7 920 @ 3.5 GHz

slow = 4.49
fast = 4.442
sum = 99999990000000000

英特尔至强 X5482 Harpertown @ 3.2 GHz

slow = 3.684
fast = 3.717
sum = 99999990000000000
  • Core i7 的数字没有变化。显然它可以处理 对于这个基准测试来说,错位没有问题。
  • 现在,Core 2 Xeon 的两个版本显示相同的时间。这证实了 Core 2 架构上存在未对齐问题。

摘自我的评论:

如果您省略#pragma pack,编译器将使所有内容保持一致,这样您就不会看到这个问题。所以这实际上是一个例子,如果你misuse #pragma pack.

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

位对齐可提高空间和性能 的相关文章

  • 在 xaml 中编写嵌套类型时出现设计时错误

    我创建了一个用户控件 它接受枚举类型并将该枚举的值分配给该用户控件中的 ComboBox 控件 很简单 我在数据模板中使用此用户控件 当出现嵌套类型时 问题就来了 我使用这个符号来指定 EnumType x Type myNamespace
  • 根据属性的类型使用文本框或复选框

    如果我有这样的结构 public class Parent public string Name get set public List
  • 随着时间的推移,添加到 List 变得非常慢

    我正在解析一个大约有 1000 行的 html 表 我从一个字符串中添加 10 个字符串 td 每行到一个list td
  • 如何在 C# 中打开 Internet Explorer 属性窗口

    我正在开发一个 Windows 应用程序 我必须向用户提供一种通过打开 IE 设置窗口来更改代理设置的方法 Google Chrome 使用相同的方法 当您尝试更改 Chrome 中的代理设置时 它将打开 Internet Explorer
  • free 和 malloc 在 C 中如何工作?

    我试图弄清楚如果我尝试 从中间 释放指针会发生什么 例如 看下面的代码 char ptr char malloc 10 sizeof char for char i 0 i lt 10 i ptr i i 10 ptr ptr ptr pt
  • -webkit-box-shadow 与 QtWebKit 模糊?

    当时有什么方法可以实现 webkit box shadow 的工作模糊吗 看完这篇评论错误报告 https bugs webkit org show bug cgi id 23291 我认识到这仍然是一个问题 尽管错误报告被标记为RESOL
  • 如何在 C++ 中标记字符串?

    Java有一个方便的分割方法 String str The quick brown fox String results str split 在 C 中是否有一种简单的方法可以做到这一点 The 增强分词器 http www boost o
  • C++ 多行字符串原始文字[重复]

    这个问题在这里已经有答案了 我们可以像这样定义一个多行字符串 const char text1 part 1 part 2 part 3 part 4 const char text2 part 1 part 2 part 3 part 4
  • 重载 (c)begin/(c)end

    我试图超载 c begin c end类的函数 以便能够调用 C 11 基于范围的 for 循环 它在大多数情况下都有效 但我无法理解和解决其中一个问题 for auto const point fProjectData gt getPoi
  • 方程“a + bx = c + dy”的积分解

    在等式中a bx c dy 所有变量都是整数 a b c and d是已知的 我如何找到整体解决方案x and y 如果我的想法是正确的 将会有无限多个解 由最小公倍数分隔b and d 但我只需要一个解决方案 我可以计算其余的 这是一个例
  • 人脸 API DetectAsync 错误

    我想创建一个简单的程序来使用 Microsoft Azure Face API 和 Visual Studio 2015 检测人脸 遵循 https social technet microsoft com wiki contents ar
  • ASP.NET Core 3.1登录后如何获取用户信息

    我试图在登录 ASP NET Core 3 1 后获取用户信息 如姓名 电子邮件 id 等信息 这是我在登录操作中的代码 var claims new List
  • 为什么这个字符串用AesCryptoServiceProvider第二次解密时不相等?

    我在 C VS2012 NET 4 5 中的文本加密和解密方面遇到问题 具体来说 当我加密并随后解密字符串时 输出与输入不同 然而 奇怪的是 如果我复制加密的输出并将其硬编码为字符串文字 解密就会起作用 以下代码示例说明了该问题 我究竟做错
  • 用于选择特定 div 中具有特定类的锚元素的 jQuery 选择器是什么

    我有一些这样的代码 我想选择每个 a 带有类的标签status在 div 中foo div a class status a div 你可以这样做 foo find status a
  • LINQ:使用 INNER JOIN、Group 和 SUM

    我正在尝试使用 LINQ 执行以下 SQL 最接近的是执行交叉联接和总和计算 我知道必须有更好的方法来编写它 所以我向堆栈团队寻求帮助 SELECT T1 Column1 T1 Column2 SUM T3 Column1 AS Amoun
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • C++ 继承的内存布局

    如果我有两个类 一个类继承另一个类 并且子类仅包含函数 那么这两个类的内存布局是否相同 e g class Base int a b c class Derived public Base only functions 我读过编译器无法对数
  • 为什么C++代码执行速度比java慢?

    我最近用 Java 编写了一个计算密集型算法 然后将其翻译为 C 令我惊讶的是 C 的执行速度要慢得多 我现在已经编写了一个更短的 Java 测试程序和一个相应的 C 程序 见下文 我的原始代码具有大量数组访问功能 测试代码也是如此 C 的
  • C# 使用“?” if else 语句设置值这叫什么

    嘿 我刚刚看到以下声明 return name null name NA 我只是想知道这在 NET 中叫什么 是吗 代表即然后执行此操作 这是一个俗称的 条件运算符 三元运算符 http en wikipedia org wiki Tern
  • Mono 应用程序在非阻塞套接字发送时冻结

    我在 debian 9 上的 mono 下运行一个服务器应用程序 大约有 1000 2000 个客户端连接 并且应用程序经常冻结 CPU 使用率达到 100 我执行 kill QUIT pid 来获取线程堆栈转储 但它总是卡在这个位置

随机推荐

  • 为什么查询对象设计模式

    我试图理解 查询对象设计模式 我无法找到好的和简单的例子 有人可以帮助我理解这个设计模式的用途以及我们可以在什么问题上实现它吗 查询设计模式通常与存储库设计模式结合使用 让我们举一个例子 然后我将给出一篇很好的文章来阅读 假设我们有一个数据
  • 嵌套弹性框:IE11 不尊重最大宽度:100%

    我正在研究两列布局 两列都会显示一个 iframe 两者的宽度都将被定义为内联样式 在 CMS 中设置 如果 iframe 小于列 则它应垂直居中 如果它比列大 它应该收缩到列的最大宽度 即近 50 宽 是的 这可能可以在不使用两次 Fle
  • 如何在 C# 中不使用科学记数法将字符串反序列化为 JObject

    我有一个像这样的字符串 var str data someProperty 0 00001 当我像这样解析它为 JObject 时 var jObject JObject Parse str 我的 jObject 看起来像这样 data s
  • 使用 Excel VBA 控制 Web 浏览器

    我被分配了自动化基于 Web 的任务 针对 HTTPS 网站 的任务 用户当前正在用数据填充Excel工作表 他们现在希望以一种直接控制浏览器并填充数据的方式自动化Excel 我发现 iMacros Scripting 版本作为执行此操作的
  • SwiftUI:带有图像的按钮在真实 iPhone 上有灰色边框,但在模拟模式下工作正常

    我正在尝试制作简单的应用程序 该应用程序似乎在模拟模式下运行良好 但在我的 iPhone 上测试按钮看起来与模拟 iPhone 不同 在这里链接模拟图片 在此输入图像描述 https i stack imgur com PyBDM png
  • 网站图标在 Internet Explorer 中不工作

    我已尽一切努力使 favicon 工作 但仅在 IE 上不起作用 这是在 我尝试使用 favicon co uk 和 favicon generator org 创建一个 favicon 但在 IE 中没有任何效果 它是 16x16 和 i
  • s.Count(Char.IsLetter) 有什么问题

    F let s bugs 42 bunny s Count fun c gt Char IsLetter c s Where fun c gt Char IsLetter c ToArray s Where Char IsLetter To
  • 在 NSURLConnection 中从 Swift 中的completionHandler 中获取数据

    我正在尝试编写一个函数来执行异步 GET 请求 并返回响应 作为任何数据类型 但这里是 NSData 这个问题是基于 如何快速使用 NSURLConnectioncompletionHandler https stackoverflow c
  • ClickOnce如何设置图标

    尝试在 ClickOnce 安装中设置图标的示例 但没有任何进展 在发布 gt 选项 gt 文件关联中设置 application的扩展名并选择我的图标 也许我正在寻找错误的方式来设置图标 但我的 app appref ms 仍然有默认图标
  • 序列化为 JSON 时排除集合中的特定项目

    我试图 挑选 我想要序列化的特定类型集合中的哪些对象 设置示例 public class Person public string Name get set public List
  • GCE使用云存储桶作为挂载驱动器

    有没有办法将存储桶挂载到实例 以便网络服务器可以将其用作存储 如果没有 如何在不添加另一个带有操作系统的永久磁盘的情况下向实例添加更多存储 除了附加新的永久性磁盘之外 您还可以使用许多基于 FUSE 的实用程序将 Google Cloud
  • 如何在提交时重新加载页面

    我有一个包含表单的 Bootstrap Modal 该模式还包含一个提交和取消按钮 取消按钮工作正常 并且正在成功关闭模态框 现在 根据我对模态框提交按钮单击的要求 通过将用户输入传递到 Web 服务 表单已成功提交 但模态框并未关闭 另外
  • AndroidX - 程序类型已存在:androidx.annotation.BoolRes

    我今天尝试使用 Android Studio 中的 重构 gt 迁移到 AndroidX 选项将当前项目迁移到 AndroidX 每当我尝试编译我的应用程序时 我都会收到一个 程序类型已存在 androidx annotation Bool
  • 在设备上将 GIF 转换为 MP4

    是否可以获取远程 但如果需要的话我可以先下载 GIF 序列并在设备上制作 MPMovies PlayerViewController 可播放的 mp4 我尝试过使用http api online convert com http api o
  • MongoDB 相当于 SQL“OR”

    所以 MongoDB在查找记录时默认使用 AND 例如 db users find age gte 30 lte 40 上述查询找到用户 gt 30AND 我如何找到 OR gt 40 岁 没有 OR 运算符 但他们说你仍然可以这样做 ht
  • 添加“constexpr”可以改变行为吗?

    给定两个程序 源代码中唯一的区别是其中一个的存在或不存在constexpr 有没有可能程序的含义发生了变化 换句话说 如果有一个编译器选项要求编译器努力推断constexpr在可能的情况下 它会破坏现有的标准代码和 或以不好的方式改变其含义
  • 在 C# 中对从 1 开始的数组进行变基

    我在 C 中有一个基于 1 的数组 通过调用 Excel Range 的 get Value 生成 例如 我得到一个二维数组 object ExcelData object MySheet UsedRange get Value Excel
  • 使用react-native-firebase在反应本机应用程序中链接器命令失败

    我使用react native firebase库开发了一个react Native应用程序 我想设置我的应用程序图标 所以我使用了这个库 npm install g yo generator rn toolbox from here ht
  • dplyr `left_join()` 不能将字符对象用作 LHS 变量 [重复]

    这个问题在这里已经有答案了 I can使用以下命令连接包含两个不同名称的变量的两个数据集dplyr left join by c name1 name2 我想要使用角色对象加入 left join by c nameOb1 nameOb2
  • 位对齐可提高空间和性能

    在书里游戏编码完成 第三版 https rads stackoverflow com amzn click com 1584506806作者提到了一种减少数据结构大小的技术and提高访问性能 本质上 它依赖于当成员变量内存对齐时获得性能的事