SSE、内在函数和对齐

2024-04-26

我使用大量 SSE 编译器内在函数编写了一个 3D 矢量类。一切都工作正常,直到我开始使用 new 来实例化具有 3D 向量作为成员的类。我在发布模式下经历了奇怪的崩溃,但在调试模式下却没有,反之亦然。

因此,我阅读了一些文章,并认为我需要将拥有 3D 矢量类实例的类也对齐到 16 字节。所以我刚刚添加了_MM_ALIGN16 (__declspec(align(16))在类前面,如下所示:

_MM_ALIGN16 struct Sphere
{
    // ....

    Vector3 point;
    float radius
};

起初这似乎解决了问题。但是在更改了一些代码之后,我的程序再次开始以奇怪的方式崩溃。我又在网上搜索了一下,发现了一个blog http://ernsthot.blogspot.de/2009/03/diving-into-sse-alignment-issues.html文章。我尝试了作者 Ernst Hot 所做的方法来解决这个问题,它也对我有用。我向我的类添加了新的和删除的运算符,如下所示:

_MM_ALIGN16 struct Sphere
{
    // ....

    void *operator new (unsigned int size)
     { return _mm_malloc(size, 16); }

    void operator delete (void *p)
     { _mm_free(p); }

    Vector3 point;
    float radius
};

恩斯特提到这种方法也会有问题,但他只是链接到一个不再存在的论坛,而没有解释为什么会出现问题。

所以我的问题是:

  1. 定义运算符有什么问题?

  2. 为什么不添加_MM_ALIGN16到类定义就够了吗?

  3. 处理 SSE 内在函数带来的对齐问题的最佳方法是什么?


首先,您必须关心两种类型的内存分配:

  • 静态分配。为了使自动变量正确对齐,您的类型需要正确的对齐规范(例如__declspec(align(16)), __attribute__((aligned(16))),或者你的_MM_ALIGN16)。但幸运的是,只有当类型成员(如果有)给出的对齐要求不充分时,您才需要这样做。所以你不需要这个Sphere,鉴于你的Vector3已经正确对齐。如果你的Vector3包含一个__m128成员(这很可能,否则我建议这样做),那么你甚至不需要它Vector3。因此,您通常不必弄乱编译器特定的对齐属性。

  • 动态分配。简单的部分就讲这么多。问题是,C++ 在最低级别上使用与类型无关的内存分配函数来分配任何动态内存。这仅保证所有标准类型的正确对齐,这些标准类型可能恰好是 16 字节,但不能保证。

    为了弥补这一点,你必须重载内置的operator new/delete实现您自己的内存分配并在后台使用对齐的分配函数而不是旧的malloc。超载operator new/delete本身就是一个主题,但并不像乍一看那么困难(尽管您的示例还不够),您可以在这个优秀的常见问题解答 https://stackoverflow.com/q/7194127/743214.

    不幸的是,您必须为具有任何需要非标准对齐的成员的每种类型执行此操作,在您的情况下Sphere and Vector3。但是,为了使其变得更容易,您可以做的就是为这些运算符创建一个具有适当重载的空基类,然后从该基类派生所有必要的类。

    大多数人有时容易忘记的是标准分配器std::alocator使用全局的operator new对于所有内存分配,因此您的类型无法与标准容器(以及std::vector<Vector3>这种用例并不罕见)。您需要做的是创建自己的标准一致分配器并使用它。但为了方便和安全,实际上更好的是专注于std::allocator对于您的类型(也许只是从您的自定义分配器派生它),以便始终使用它,并且您不需要每次使用时都关心使用正确的分配器std::vector。不幸的是,在这种情况下,您必须再次针对每种对齐类型专门化它,但是一个小的邪恶宏可以帮助解决这个问题。

    此外,您还必须注意使用全局的其他事情operator new/delete而不是您自定义的,例如std::get_temporary_buffer and std::return_temporary_buffer,并在必要时照顾这些人。

不幸的是,我认为还没有更好的方法来解决这些问题,除非您使用的平台本身就与 16 对齐并了解这一点。或者你可能只是让全局超载operator new/delete始终将每个内存块对齐到 16 字节,并且无需关心包含 SSE 成员的每个类的对齐,但我不知道这种方法的含义。在最坏的情况下,它只会导致内存浪费,但话又说回来,您通常不会在 C++ 中动态分配小对象(尽管std::list and std::map可能对此有不同的看法)。

总结一下:

  • 使用以下方法来注意静态内存的正确对齐__declspec(align(16)),但前提是它还没有被任何成员照顾(通常是这种情况)。

  • 超载operator new/delete对于每种类型都有一个具有非标准对齐要求的成员。

  • 制作一个自定义的符合标准的分配器以在对齐类型的标准容器中使用,或者更好的是,专门化std::allocator对于每个对齐类型。


最后一些一般性建议。通常,在执行许多向量运算时,您只能从计算量大的块中的 SSE 中获益。为了简化所有这些对齐问题,特别是照顾包含一个的每个类型的对齐问题Vector3,这可能是一个好方法,创建一个特殊的 SSE 向量类型,并且仅在冗长的计算中使用它,使用普通的非 SSE 向量来存储和成员变量。

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

SSE、内在函数和对齐 的相关文章

  • C++:创建一个由用户输入大小的数组

    我想知道我们是否可以创建一个具有用户指定大小的数组 Ex int a cout lt lt Enter desired size of the array cin gt gt a int array a 上面的程序将不起作用 因为数组大小必
  • 如何通过MFC将应用程序设置保存到注册表中?

    我有一个由 MFC 项目向导创建的 MFC 应用程序 我想在注册表中保存 读取应用程序设置 所以问了这个question https stackoverflow com questions 1880275 good c registry w
  • 在 C/C++ 中读取和写入二进制文件的中间部分

    如果我有一个大的二进制文件 假设它有 100 000 000 个浮点数 C 或 C 有没有办法打开文件并读取特定的浮点数 而不必将整个文件加载到内存中 即我如何快速找出第 62 821 214 个浮点是什么 第二个问题 有没有办法更改文件中
  • 改变 RGB 颜色的色调

    我正在尝试编写一个函数来改变 RGB 颜色的色调 具体来说 我在 iOS 应用程序中使用它 但数学是通用的 下图显示了 R G 和 B 值如何随色调变化 看起来 编写一个函数来改变色调似乎应该是一个相对简单的事情 而不需要对不同的颜色格式进
  • 为什么 C++ Concepts TS 中同时存在变量和函数概念?

    我一直在看 C 1zN4377 http www open std org jtc1 sc22 wg21 docs papers 2015 n4377 pdfGCC 6 中正在实现的概念 TS 草案 我不明白拥有两种不同概念的目的 变量概念
  • 如何使用 PowerShell 使用 C# DLL 中存在的类的 New-Object

    例如 我有一个 C 类 public class MyComputer PSObject public string UserName get return userName set userName value private strin
  • c++1y 模式下的 Clang >= 3.3 无法解析 标头

    我有一个项目可以在 g 4 8 1 和 c 11 模式下 clang gt 3 3 下正确编译和运行 然而 当我切换到实验时 std c 1y模式下 clang 3 3 但不是 g 在
  • 如何将文本框中删除的字符替换为0

    在winforms中 如何用零替换删除的字符 例如 文本框中为 12 45 如果我们删除小数点后 它应该变成12 00 同样的方法删除前面的000 45 默认值应为 000 00 Use a 蒙版文本框 http msdn microsof
  • ReportViewer“缺少 URL 参数:名称”

    在一个网络应用程序中 我正在处理 ReportViewer 时不断出现错误 缺少 URL 参数 名称 我找到了原因 但没有找到解决方案 导致报告查看器出现异常的 url Reserved ReportViewerWebControl axd
  • 慢速 WPF 文本框

    我正在开发一个简单的串行数据查看器 它将用于观察传输到计算机串行端口之一的数据 我使用 C 和 WPF 编写了一个测试应用程序 它只是将最近读取的行放入文本块中 但是 它会跳过所有其他行 我的理论是 在 WPF 渲染窗口之前 新数据会被放入
  • 如何检测机器是否加入域?

    如何检测计算机是否已加入 Active Directory 域 相对于工作组模式 如果没有必要的话 不要用 pinvoke 来愚弄 参考System DirectoryServices 然后调用 System DirectoryServic
  • 如何在 MSBuild NuGet 包生成的 .nuspec 中注入自定义依赖项

    我正在尝试迁移到使用 MSBuildPack支持使用 csproj 生成项目 NuGet 包 其中在开发过程中使用本地 dll 来构建项目 但在使用 MSBuild 打包 项目时需要替换 交换它们以引用生成的 nuspec 中的外部 NuG
  • 弹出窗口或弹出窗口显示附加信息

    我想在我的应用程序顶部显示带有附加信息的弹出窗口 我的信息是Listview大约 500 个项目我都尝试过 有问题flyout gt 它里面可能有scrollViewer 所以我的列表视图不能正确虚拟化 其他一切都可以 有我的代码 Flyo
  • 如何存储将被多个不同类访问的字符串常量? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 关于堆栈溢出有太多不同的答案 声明一个命名空间 并在 hpp 文件中将所有字符串标记为 extern const 并在 cpp 文件中放置它们的
  • 如果键不是映射中的初始化键,STL map[key] 返回什么? [复制]

    这个问题在这里已经有答案了 这是一些示例代码 include
  • 使用指针隐藏实现(Pimpl 惯用语)

    是否有可能实现以下目标 x hpp 该文件被许多其他类包含 class x impl forward declare class x public methods private x impl impl x cpp 实施 include
  • 当数据源中只有 1 项时 FormView 不显示 PagerTemplate

    我有一个带有自定义 PagerTemplate 的 FormView 控件和我自己的分页 LinkBut ton 一切都很好 直到我加载的数据集仅包含一个记录 项目并完全隐藏 PagerTemplate 我在网上搜索了一下 找到了几个答案
  • 在源代码和预编译二进制文件之间切换

    我们的应用程序中有大量的库 库是用 C 或 C 编写的 平台 net Framework Windows 64 位 将所有内容编译为源代码需要花费大量时间 我们正在考虑切换到预构建的二进制文件 但我们仍然希望保留返回源代码的可能性 作为版本
  • 计算 .NET Core 项目的代码指标?

    我正在研究 ASP NET Core 和 NET Core 项目 对于经典的 C 项目 Visual Studio 2015 具有计算代码指标的功能 对于 NET Core 预览版 2 工具中缺少支持 在工具更加完整之前 有人知道解决方法吗
  • 提高批量请求的野兽内存使用率

    我运行这个boost beast 客户端 异步 ssl http www boost org doc libs develop libs beast example http client async ssl http client asy

随机推荐

  • 如何获取子进程的返回值?

    程序计算从 1 到 N 的数字之和 子进程计算偶数之和 父进程计算奇数之和 我想在父进程中获取子进程的返回值 我怎么做 include
  • 如何从 Twig 中的多维数组中获取值?

    我的数组 strs key id 的 var dump 给出以下结果 array 2 0 gt array 4 8259 gt string 8260 ouvrir 1 8260 gt string 8261 fichier 2 8261
  • 使用 Json.net 解析 JSON

    我正在尝试使用 JSon Net 库解析一些 JSON 该文档似乎有点稀疏 我对如何完成我需要的内容感到困惑 这是我需要解析的 JSON 格式 displayFieldName OBJECT NAME fieldAliases OBJECT
  • 在其他包中使用 main.go 中声明的结构

    我有一个结构体声明于main go如下所示 type Organization struct ID string json id Count int json count node count 我有一个名为configuration并有这样
  • 当鼠标悬停在图标上时,字形会改变颜色

    我怎样才能让它工作 这样当我将鼠标悬停在 li gt a 时 它也会改变我的字形图标上的颜色 我在下面列出了我的 html 和我的内容tryed在CSS中做 但这只会改变它if我将鼠标悬停在字形图标而不是 a 上 和yes我也尝试在我的 a
  • 如何使用 PDF.js 显示 PDF(以 Base64 存储)中的所有页面?

    我正在使用以下脚本使用 PDF js 显示 PDF 但它在画布上没有显示任何内容 你能告诉我我哪里出了问题吗 我尝试在线查找文档 但找不到任何帮助 Model B 是 base64 字符串
  • wpf xceed工具包水印文本框使水印显示直到第一次输入

    默认行为是当文本框获得焦点时水印消失 我想让水印内容仅在用户键入第一个字符时消失 然后在清除文本后重新出现 有人有好的方法来实现这一点吗 我已经为你调整了默认样式 现在 水印默认显示为 稍暗 默认系统 非活动文本 颜色 并且当水印接收焦点但
  • 使用 @Valid 进行 Spring 验证

    我正在验证传入属性 但验证器甚至捕获未注释的其他页面 Valid RequestMapping value showMatches spr method RequestMethod GET public ModelAndView showM
  • 如何从存储库中删除 Sonatype Nexus OSS(3) 组件

    这是我的第一个问题 我尽力做到最好 如果有什么问题 请简单地告诉我 我会纠正自己 我是 Sonatypes Nexus 3 OSS 的新手 我找不到从我的存储库中删除组件的方法 我的存储库中的一个包已变得无用 现在我想将其删除 我已经删除了
  • spring data neo4j 5 - 没有名为“sessionFactory”的bean可用

    我正在使用 spring data neo4j 5 0 7 RELEASE 和 spring 5 0 6 RELEASE 使用文档中的配置https github com spring projects spring data neo4j
  • 如何让 G1 打印更多日志详细信息?

    我正在测试基于 Jetty 的 API 与基于 Netty 的 API 实验中唯一的区别是我使用哪个 API 相同的应用程序 相同的服务器 相同的内存配置 相同的负载等 我使用基于 Netty 的 API 时会得到更长的 GC 暂停 大多数
  • React Native 上的 MQTT?

    将 MQTT 添加到我的反应原生项目时 我很难找到正确的方法 该项目需要在 iOS 和 Android 上运行 因此理想情况下 MQTT 可以在 javascript 端处理 我意识到移动节点和经典节点的网络巢穴是不同的 所以我开始沿着分叉
  • 自定义 Windows 7 登录 [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我如何为 Windows 7 登录屏幕进行编程 不仅仅是替换背景图像 就像我希望它通过 RFID 阅读器进行身份验证一样 我能做到吗 我知道 XP 可
  • 经济模拟的算法?

    我想创建一个游戏 玩家可以创建不同价格的不同产品 称为报价 然后我给他们一定数量的客户 称为需求 现在 我想要一个算法来确定每个参与者的市场份额 当然 我现在就可以使用随机的方式来制作我的 但在这样做之前 我更愿意先问一下 因为我确信在我之
  • 我可以在css中指定maxlength吗?

    我可以用 CSS 中的某些内容替换 maxlength 属性吗
  • 如何根据文件名将文件移动到不同的目录?

    好的 我创建了一个程序 它将根据创建日期重命名目录中的文件 我现在需要能够根据创建日期将这些文件移动到不同的目录中 20131202 1 jpg 将进入名为 20131202 的文件夹 名为 20131203 2 jpg 的文件将进入名为
  • 如何在ios中获取今天日期的开始和结束时间? [复制]

    这个问题在这里已经有答案了 我使用此代码获取当前日期和时间 let today NSDate NSDate let dateFormatter NSDateFormatter NSDateFormatter dateFormatter ti
  • 多个网站,单点登录设计[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我有个问题 我最近一直在做一些工作的一个客户有一系列具有不同登录机制的网站 他正在寻求慢慢迁移到单点登录他的网站机制 全部写在asp net m
  • 使用 Nodejs 和 body-parser 发布表单数据

    我现在已经进行了几次不同的在线尝试 但我的帖子数据一直未定义 并且 console log JSON stringify req body 也没有返回任何内容 所以我在某个地方出错了 HTML
  • SSE、内在函数和对齐

    我使用大量 SSE 编译器内在函数编写了一个 3D 矢量类 一切都工作正常 直到我开始使用 new 来实例化具有 3D 向量作为成员的类 我在发布模式下经历了奇怪的崩溃 但在调试模式下却没有 反之亦然 因此 我阅读了一些文章 并认为我需要将