没有编译器优化的 SSE 内在函数

2023-12-23

我是 SSE 内在函数的新手,并尝试通过它来优化我的代码。这是我的程序,用于计算等于给定值的数组元素。

我将代码更改为 SSE 版本,但速度几乎没有改变。我想知道我是否以错误的方式使用SSE......

此代码用于不允许我们启用编译器优化选项的分配。

无 SSE 版本:

int get_freq(const float* matrix, float value) {

    int freq = 0;

    for (ssize_t i = start; i < end; i++) {
        if (fabsf(matrix[i] - value) <= FLT_EPSILON) {
            freq++;
        }
    }

    return freq;
}

上交所版本:

#include <immintrin.h>
#include <math.h>
#include <float.h>

#define GETLOAD(n) __m128 load##n = _mm_load_ps(&matrix[i + 4 * n])
#define GETEQU(n) __m128 check##n = _mm_and_ps(_mm_cmpeq_ps(load##n, value), and_value)
#define GETCOUNT(n) count = _mm_add_ps(count, check##n)

    int get_freq(const float* matrix, float givenValue, ssize_t g_elements) {

        int freq = 0;
        int i;

        __m128 value = _mm_set1_ps(givenValue);
        __m128 count = _mm_setzero_ps();
        __m128 and_value = _mm_set1_ps(0x00000001);


        for (i = 0; i + 15 < g_elements; i += 16) {
            GETLOAD(0); GETLOAD(1); GETLOAD(2); GETLOAD(3);
            GETEQU(0);  GETEQU(1);  GETEQU(2);  GETEQU(3);
            GETCOUNT(0);GETCOUNT(1);GETCOUNT(2);GETCOUNT(3);
        }

        __m128 shuffle_a = _mm_shuffle_ps(count, count, _MM_SHUFFLE(1, 0, 3, 2));
        count = _mm_add_ps(count, shuffle_a);
        __m128 shuffle_b = _mm_shuffle_ps(count, count, _MM_SHUFFLE(2, 3, 0, 1));
        count = _mm_add_ps(count, shuffle_b);
        freq = _mm_cvtss_si32(count);


        for (; i < g_elements; i++) {
            if (fabsf(matrix[i] - givenValue) <= FLT_EPSILON) {
                freq++;
            }
        }

        return freq;
    }

如果你需要编译-O0,然后在一条语句中执行尽可能多的操作。在正常代码中,int a=foo(); bar(a);将编译为与以下相同的 asmbar(foo()), 但在-O0代码,第二个版本可能会更快,因为它不会将结果存储到内存中,然后为下一条语句重新加载它。

-O0旨在通过调试提供最可预测的结果,这就是为什么在每个语句之后所有内容都存储到内存中的原因。这对于性能来说显然是可怕的。

I wrote 前段时间有个大回答 https://stackoverflow.com/a/32001196/224132对于像您这样的愚蠢任务的其他人提出的不同问题,需要他们进行优化-O0。其中一些可能会有所帮助。


不要在这项任务上太努力。可能您发现的大多数“技巧”可以使您的代码运行得更快-O0只会对-O0,但启用优化后没有区别。

在现实生活中,代码通常使用 clang 或 gcc 编译-O2至少,有时-O3 -march=haswell或任何自动矢量化的东西。 (调试完成后,您就可以进行优化了。)


回复:您的更新:

现在它可以编译了,可以看到 SSE 版本中可怕的 asm。我把它在 godbolt 上以及实际编译的标量代码版本 http://gcc.godbolt.org/#compilers:!((compiler:g530,options:%27-xc+-O0+-Wall+-fno-verbose-asm%27,sourcez:MQSwdgxgNgrgJgUwAQB4QFt3gC4CdwB0AFgHwBQoksiq6AhtkceZdPMigGZQD2DzZMjiQBzBNgD6nXAgCOEgM4Q6UOrgAUEHmAXYk3PtgBUSenhAAPADT7eDJADcVMBDYUKQALwQS9IiQhQCOgIYNgKAJRIAN6CSPFIwtJySAC8SAAMANxxCZw8uEjq7l4%2BeiBpmVmJqKIBQSFhCtUgANStUbEJ3YmcRZx0AEYKnOpm%2BBYA2iAAukgAtI7OCFEo6QBiADIAKhIAogAKAMoAkpsA8gBynWQ9d/oysu0590gAvrcJH5/xMtgwuDADzkOW%2BwEQnHAyAA4ntthcAIIAEXUYCiEgk6AAjAAmAAcSDscGAwCB6Ux6AkRIkAAcFOoAGTjSzTJCtJAAFiQJjAMwiFAhUKQsO2ewAigBVVHozG4gkQIgICAAaxJZKQFIkdDAcFp9M1EHQNLkevURLVNicsBWNm1uqtLn54IQkLAMLhAGFzhLLttpUgtDAwpVNXQ4Lq6ZoeEHsDYFUrVaT%2BT9EsGxJJkrIozo9AYGCZmdZbIZRCAHKEAGrLNweby%2BOqBYKhcI3FPdJKPSrZNsJYQgHI9%2BIY7H4pbWkOYRTiLGmkRlyvLCIve7DuUB6PB8mThTiby4HimpeDjWy0d2iQO5Bbyk77AzyMZCwZZ8vjJYo%2B5O75QrqCrpbI1OyWIAKy1P4jaNOELRsukWIAGw3K83QioiKIZEuwpwqh6jvtUKHnMi6g4hh%2BGEQAzEeSEJCK4pSuh1SYaKko4RhjG0URrE0cxFHLlRIpej6fr0fx3q%2BixWQiYJHESZ6ol%2Bjxx7fK8q6jgoRAwJw3A%2BHQE43upmlBKagZhHGG6xhqACyFkSEcAASErrFsew4TYGQ2GRNjEZR9zGXo15auGRlmW4%2BlaVq3l3CpBJqRpYWDLpiihYZka%2BaZMY2BIVk2fZjmbM5OLua5NjvhFPS%2BQlYYRvSqVIDFBk%2BIMpXdJmCUQA44QKIoIBkTiUYxh%2Bx7fkU0EoA2DTNs0iTtIhVG9P0QwjGMDATNMcyLHO5ZgFW1qrBsOz7McZxXDNs15I8zzHt0HyvEp9x/ACQKZrx7xAAAA%3D%3D)),filterAsm:(commentOnly:!t,directives:!t,intel:!t,labels:!t),version:3。内在函数通常在禁用优化的情况下编译得非常糟糕,内联函数仍然具有参数和返回值,从而导致实际加载/存储往返 https://stackoverflow.com/questions/54073295/why-is-this-c-wrapper-class-not-being-inlined-away(存储转发延迟)即使__attribute__((always_inline)). See 禁用优化后,演示代码未能显示出 4 倍快的 SIMD 速度 https://stackoverflow.com/questions/27075540/demonstrator-code-failing-to-show-4-times-faster-simd-speed-with-optimization-di例如。

标量版本的结果要好得多。它的源在一个表达式中完成所有操作,因此临时值保留在寄存器中。不过,循环计数器仍然在内存中,例如,在 Haswell 上,它的瓶颈最多为每 6 个周期一次迭代。 (参见x86 /questions/tagged/x86标记 wiki 以获取优化资源。)


顺便说一句,矢量化fabsf()很容易,看使用 SSE 计算绝对值的最快方法 https://stackoverflow.com/questions/32408665/fastest-absolute-value-calculator-using-sse/32422471#32422471。与小于的 SSE 比较应该可以为您提供与标量代码相同的语义。 (但更难获得-O0为了不吸)。

您可能会做得更好,只需手动展开标量版本一两次,因为-O0太糟糕了。

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

没有编译器优化的 SSE 内在函数 的相关文章

  • asp.net 文本框文本模式数字,仅允许数字

    我只是想知道 ASP NET 中是否有一种方法只允许文本框中的数字textmode number 当我使用这个时
  • 使用具有现有访问令牌的 Google API .NET 客户端

    用例如下 移动应用程序正在通过 Google 对用户进行身份验证 并且在某些时候 我们需要将用户的视频发布到他的 YouTube 帐户 出于实际原因 实际发布应该由后端完成 已经存储在那里的大文件 由于用户已经通过应用程序的身份验证 因此应
  • C#动态支持吗?

    看完之后这个帖子 https stackoverflow com questions 2674906 when should one use dynamic keyword in c sharp 4 0k和链接 我还有 2 个问题 问题 1
  • 为什么要序列化对象需要 Serialized 属性

    根据我的理解 SerializedAttribute 不提供编译时检查 因为它都是在运行时完成的 如果是这样 那么为什么需要将类标记为可序列化呢 难道序列化器不能尝试序列化一个对象然后失败吗 这不就是它现在所做的吗 当某些东西被标记时 它会
  • JSON 数组到 C# 列表

    如何将这个简单的 JSON 字符串反序列化为 C 中的列表 on4ThnU7 n71YZYVKD CVfSpM2W 10kQotV 这样 List
  • 从多个类访问串行端口

    我正在尝试使用串行端口在 arduino 和 C 程序之间进行通信 我对 C 编程有点陌生 该程序有多种用户控制形式 每一个都需要访问串口来发送数据 我需要做的就是从每个类的主窗体中写入串行端口 我了解如何设置和写入串行端口 这是我的 Fo
  • 检查算术运算中的溢出情况[重复]

    这个问题在这里已经有答案了 可能的重复 检测 C C 中整数溢出的最佳方法 https stackoverflow com questions 199333 best way to detect integer overflow in c
  • ASP MVC:服务应该返回 IQueryable 的吗?

    你怎么认为 你的 DAO 应该返回一个 IQueryable 以便在你的控制器中使用它吗 不 您的控制器根本不应该处理任何复杂的逻辑 保持苗条身材 模型 而不是 DAO 应该将控制器返回给视图所需的所有内容 我认为在控制器类中看到查询 甚至
  • C 语言中 =+(等于加)是什么意思?

    我碰到 与标准相反 今天在一些 C 代码中 我不太确定这里发生了什么 我在文档中也找不到它 In ancientC 版本 相当于 它的残余物与最早的恐龙骨头一起被发现 例如 B 引入了广义赋值运算符 使用x y to add y to x
  • 在非活动联合成员上使用“std::addressof”是否定义明确[重复]

    这个问题在这里已经有答案了 下面的代码是尝试实现constexpr的版本offsetof在 C 11 中 它可以在 gcc 7 2 0 和 clang 5 0 0 中编译 这取决于申请std addressof工会非活跃成员的成员 这是明确
  • 如何在c#中的内部类中访问外部类的变量[重复]

    这个问题在这里已经有答案了 我有两个类 我需要声明两个类共有的变量 如果是嵌套类 我需要访问内部类中的外部类变量 请给我一个更好的方法来在 C 中做到这一点 示例代码 Class A int a Class B Need to access
  • g++ 对于看似不相关的变量“警告:迭代...调用未定义的行为”

    考虑以下代码strange cpp include
  • 有没有一种简单的方法可以让 Visual Studio 2015 使用特定的 ToolsVersion?

    使用特定版本构建项目或解决方案时msbuild我可以使用以下命令选择早期的 net 工具链 toolsversion or tv switch C Program Files x86 MSBuild 14 0 bin msbuild tv
  • 耐用功能是否适合大量活动?

    我有一个场景 需要计算 500k 活动 都是小算盘 由于限制 我只能同时计算 30 个 想象一下下面的简单示例 FunctionName Crawl public static async Task
  • 结构体指针的动态数组

    我必须使用以下代码块来完成学校作业 严格不进行任何修改 typedef struct char firstName char lastName int id float mark pStudentRecord pStudentRecord
  • strcmp 给出分段错误[重复]

    这个问题在这里已经有答案了 这是我的代码给出分段错误 include
  • 我在在线程序挑战编译器中遇到演示错误

    include
  • 用于 C# XNA 的 Javascript(或类似)游戏脚本

    最近我准备用 XNA C 开发另一个游戏 上次我在 XNA C 中开发游戏时 遇到了必须向游戏中添加地图和可自定义数据的问题 每次我想添加新内容或更改游戏角色的某些值或其他内容时 我都必须重建整个游戏或其他内容 这可能需要相当长的时间 有没
  • Googletest:如何异步运行测试?

    考虑到一个包含数千个测试的大型项目 其中一些测试需要几分钟才能完成 如果按顺序执行 整套测试需要一个多小时才能完成 通过并行执行测试可以减少测试时间 据我所知 没有办法直接从 googletest mock 做到这一点 就像 async选项
  • 使用 Crypto++ 获取 ECDSA 签名

    我必须使用 Crypto 在变量中获取 ECDSA 签名 我在启动 SignMessage 后尝试获取它 但签名为空 我怎样才能得到它 你看过 Crypto wiki 吗 上面有很多东西椭圆曲线数字签名算法 http www cryptop

随机推荐

  • VB.NET form.show() 错误

    每次我使用时 form1 show I get Reference to a non shared member requires an object reference 一直有效 不知道出了什么问题 此外 它甚至没有显示在 启动表单 下拉
  • gridView 中的复选框

    我正在 gridview 中使用复选框 为了获取复选框 id 我正在使用以下代码 for int i 0 i lt GridView1 Rows Count i CheckBox chkDelete CheckBox GridView1 R
  • 检查 UIWebView 是否已加载

    我在一个选项卡中有一个 UIWebView 可以在 viewDidLoad 中加载 但是如果用户点击其他选项卡 加载将会中断 并且 void webView UIWebView webView didFailLoadWithError NS
  • 如何发现无意的对象指针比较?

    快速问题 有没有一个好的方法来找到用途 用对象代替isEqual 完整故事 我有一堆类似这样的代码 typedef long DataKey DataKey x DataKey y if x y do stuff 我现在需要更换使用long
  • 如何让盒子始终具有相同的宽度

    这里我必须装箱 看起来像这样 div class dataViewBox div class dataViewBox Download div class dataViewBox DownloadLink span class dataVi
  • MongoDB:检查嵌套数组是否包含子数组

    我有一个数据库建模如下的用例 name XYZ gradeCards id 1234 id of the report card comments GOOD NICE WOW id 2345 comments GOOD NICE TRY 现
  • select2-rails gem 不适用于 Rails4

    我已经尝试过给出的文档select2 rails 宝石 https github com argerim select2 rails 但我的浏览器控制台仍然抛出错误 未捕获的类型错误 select2 不是函数 我在用rails 4 0 1
  • System.IO.Compression.ZipFile .NET 4.5 输出 zip 不适合 Linux/Mac/Java

    使用 NET时System IO Compression ZipFile CreateFromDirectory类结果 zip 在带有正斜杠目录分隔符的系统上被严重提取 原因 zip 名称中包含反斜杠 为了解决这个问题 有一个解决方法 cl
  • Xcode - iPhone - 配置文件与默认钥匙串中的任何有效证书/私钥对不匹配

    我尝试将我的 iPhone 添加到 Xcode4 来测试我的应用程序 我在 Apple Developer Center 中添加了设备并下载了 Provision Profile 我们每月为该帐户支付 99 美元 而且我不是唯一使用该帐户的
  • 如何生成“粗”的贝塞尔曲线?

    我正在寻找一种通过 加厚 贝塞尔曲线以编程方式生成多边形的方法 像这样的东西 我最初的想法是找到直线中的法线 并从中生成多边形 但问题是法线可能会以陡峭的曲线相互交叉 如下所示 是否有任何公式或算法可以从贝塞尔曲线生成多边形 我在互联网上找
  • 如何在 Kotlin 中获取具体化泛型参数的实际类型参数?

    Using 具体化类型参数 https kotlinlang org docs reference inline functions html reified type parameters 可以编写一个内联函数 在运行时通过反射来处理类型
  • java中正十进制值和负十进制值的正则表达式

    负十进制值和正十进制值的正则表达式 以便可以 使用模式和匹配器与字符串匹配以获得正确的实现 谁能给我提供一下吗 0 9 0 9
  • RMI 连接在本地主机上被拒绝

    我正在尝试学习 RMI 编码 当我运行 RMI 的服务器端时 连接被拒绝 这是我的服务器主要方法 public static void main String args throws Exception Implementation imp
  • 如何绑定到 SwiftUI 中可选的数据

    我很好奇 我们如何指定对属于可选部分的状态数据的绑定 例如 struct NameRecord var name var isFunny false class AppData ObservableObject Published var
  • 使用 SSZipArchive 解压缩文件 - Swift

    我正在尝试使用 SSZipArchive 框架解压缩文件 let unzipper SSZipArchive unzipFileAtPath String document toDestination String documentsUrl
  • PyQt 打印原始 PDF

    假设我有一个test pdf文件在当前目录中 我想使用以下命令将此原始文件发送到打印机PyQt 图形用户界面打印机 下面的Python3代码打印PDF源代码 我不希望 Qt 为我构建 PDF 而只是使用 gui 对话框将其发送到打印机 这应
  • NVidia CUDA 工具包 7.5.27 无法在 OS X 上安装

    下载 CUDA 工具包 DMG 可以工作 但安装程序在选择软件包后失败 并出现神秘的 软件包清单解析错误 错误 使用内部二进制文件从命令行运行安装程序也会以类似的方式失败 var log cuda installer log 处的日志文件基
  • JavaScript 数组问题

    好的 我只是回顾一下 JavaScript 中的一些基本编程原则 我是编程新手 所以请耐心等待 下面是我遇到问题的代码 特别注意数组的字符串组件 var name new Array var sales new Array var tota
  • 如何突出显示列中非空白的重复项?

    我想突出显示 I 列中连接字符串的所有重复项 并在突出显示任何重复项时提供错误消息 但是 该列中有几个空白单元格 我不希望在运行宏时这些单元格显示为重复项 我从这里得到了这个代码 Sub HighlightDuplicateValues D
  • 没有编译器优化的 SSE 内在函数

    我是 SSE 内在函数的新手 并尝试通过它来优化我的代码 这是我的程序 用于计算等于给定值的数组元素 我将代码更改为 SSE 版本 但速度几乎没有改变 我想知道我是否以错误的方式使用SSE 此代码用于不允许我们启用编译器优化选项的分配 无