位对齐可提高空间和性能

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(使用前将#替换为@)

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

  • Signalr 在生产服务器中总是陷入长轮询

    当我在服务器中托管应用程序时 它会检查服务器端事件并始终回退到长轮询 服务器托管环境为Windows Server 2012 R1和IIS 7 5 无论如何 我们是否可以解决这个问题 https cloud githubuserconten
  • 如何在 Unity 中从 RenderTexture 访问原始数据

    问题的简短版本 我正在尝试访问 Unity 中 RenderTexture 的内容 我一直在使用 Graphics Blit 使用自己的材质进行绘制 Graphics Blit null renderTexture material 我的材
  • Func 方法参数的首选命名约定是什么?

    我承认这个问题是主观的 但我对社区的观点感兴趣 我有一个缓存类 它采用类型的缓存加载器函数Func
  • 模板类的不明确多重继承

    我有一个真实的情况 可以总结为以下示例 template lt typename ListenerType gt struct Notifier void add listener ListenerType struct TimeListe
  • 在 Xamarin Android 中将图像从 URL 异步加载到 ImageView 中

    我有一个包含多个项目的 ListView 列表中的每个项目都应该有一个与之关联的图像 我创建了一个数组适配器来保存每个列表项并具有我希望加载的图像的 url 我正在尝试使用 Web 请求异步加载图像 并设置图像并在加载后在视图中更新它 但视
  • FFMPEG Seeking 带来音频伪影

    我正在使用 ffmpeg 实现音频解码器 在读取音频甚至搜索已经可以工作时 我无法找到一种在搜索后清除缓冲区的方法 因此当应用程序在搜索后立即开始读取音频时 我没有任何工件 avcodec flush buffers似乎对内部缓冲区没有任何
  • fgets() 和 Ctrl+D,三次才能结束?

    I don t understand why I need press Ctrl D for three times to send the EOF In addition if I press Enter then it only too
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • HttpClient 像浏览器一样请求

    当我通过 HttpClient 类调用网站 www livescore com 时 我总是收到错误 500 可能服务器阻止了来自 HttpClient 的请求 1 还有其他方法可以从网页获取html吗 2 如何设置标题来获取html内容 当
  • 如何在 Team Foundation 上强制发表有意义的签入评论?

    我有一个开发团队有一个坏习惯 他们写道poor签入评论 当我们必须在团队基础上查看文件的历史记录时 这使得它成为一场噩梦 我已经启用了变更集评论政策 这样他们甚至可以在签到时留下评论 否则他们不会 我们就团队的工作质量进行了一些讨论 他们很
  • 线程、进程和 Application.Exit()

    我的应用程序由主消息循环 GUI 和线程 Task Factory 组成 在线程中我调用一些第三方应用程序var p new Process 但是当我调用Application Exit 在消息循环中 我可以看到在线程中启动的进程仍在内存中
  • Windows 10 中 Qt 桌面应用程序的缩放不当

    我正在为 Windows 10 编写一个简单的 Qt Widgets Gui 应用程序 我使用的是 Qt 5 6 0 beta 版本 我遇到的问题是它根本无法缩放到我的 Surfacebook 的屏幕上 这有点难以判断 因为 SO 缩放了图
  • 用 C 实现 Unix shell:检查文件是否可执行

    我正在努力用 C 语言实现 Unix shell 目前正在处理相对路径的问题 特别是在输入命令时 现在 我每次都必须输入可执行文件的完整路径 而我宁愿简单地输入 ls 或 cat 我已经设法获取 PATH 环境变量 我的想法是在 字符处拆分
  • C 中的位移位

    如果与有符号整数对应的位模式右移 则 1 vacant bit will be filled by the sign bit 2 vacant bit will be filled by 0 3 The outcome is impleme
  • AccessViolationException 未处理

    我正在尝试使用史蒂夫 桑德森的博客文章 http blog stevensanderson com 2010 01 28 editing a variable length list aspnet mvc 2 style 为了在我的 ASP
  • 什么是 C 语言的高效工作流程? - Makefile + bash脚本

    我正在开发我的第一个项目 该项目将跨越多个 C 文件 对于我的前几个练习程序 我只是在中编写了我的代码main c并使用编译gcc main c o main 当我学习时 这对我有用 现在 我正在独自开展一个更大的项目 我想继续自己进行编译
  • 在 URL 中发送之前对特殊字符进行百分比编码

    我需要传递特殊字符 如 等 Facebook Twitter 和此类社交网站的 URL 为此 我将这些字符替换为 URL 转义码 return valToEncode Replace 21 Replace 23 Replace 24 Rep
  • char指针或char变量的默认值是什么[重复]

    这个问题在这里已经有答案了 下面是我尝试打印 char 变量和指针的默认值 值的代码 但无法在控制台上看到它 它是否有默认值或只是无法读取 ASCII 范围 include
  • 如何在 C# 中播放在线资源中的 .mp3 文件?

    我的问题与此非常相似question https stackoverflow com questions 7556672 mp3 play from stream on c sharp 我有音乐网址 网址如http site com aud
  • 更改显示的 DPI 缩放大小使 Qt 应用程序的字体大小渲染得更大

    我使用 Qt 创建了一些 GUI 应用程序 我的 GUI 应用程序包含按钮和单选按钮等控件 当我运行应用程序时 按钮内的按钮和字体看起来正常 当我将显示器的 DPI 缩放大小从 100 更改为 150 或 200 时 无论分辨率如何 控件的

随机推荐

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

    我试图理解 查询对象设计模式 我无法找到好的和简单的例子 有人可以帮助我理解这个设计模式的用途以及我们可以在什么问题上实现它吗 查询设计模式通常与存储库设计模式结合使用 让我们举一个例子 然后我将给出一篇很好的文章来阅读 假设我们有一个数据
  • 嵌套弹性框: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提高访问性能 本质上 它依赖于当成员变量内存对齐时获得性能的事