使用 Vector 的 SIMD 向量化 C# 代码运行速度比经典循环慢

2024-01-11

我看过几篇文章描述了如何Vector<T>支持 SIMD 并使用 JIT 内在函数实现,因此编译器在使用它时将正确输出 AVS/SSE/... 指令,从而允许比经典的线性循环更快的代码(例如here https://www.codeproject.com/Articles/1223361/Benchmarking-NET-Core-SIMD-performance-vs-Intel-IS).

我决定尝试重写一个方法,看看我是否能够获得一些加速,但到目前为止我失败了,矢量化代码的运行速度比原始代码慢了 3 倍,我不太确定为什么。这是检查两个是否存在的方法的两个版本Span<float>实例的所有项目对都处于同一位置,并且相对于阈值共享相同的位置。

// Classic implementation
public static unsafe bool MatchElementwiseThreshold(this Span<float> x1, Span<float> x2, float threshold)
{
    fixed (float* px1 = &x1.DangerousGetPinnableReference(), px2 = &x2.DangerousGetPinnableReference())
        for (int i = 0; i < x1.Length; i++)
            if (px1[i] > threshold != px2[i] > threshold)
                return false;
    return true;
}

// Vectorized
public static unsafe bool MatchElementwiseThresholdSIMD(this Span<float> x1, Span<float> x2, float threshold)
{
    // Setup the test vector
    int l = Vector<float>.Count;
    float* arr = stackalloc float[l];
    for (int i = 0; i < l; i++)
        arr[i] = threshold;
    Vector<float> cmp = Unsafe.Read<Vector<float>>(arr);
    fixed (float* px1 = &x1.DangerousGetPinnableReference(), px2 = &x2.DangerousGetPinnableReference())
    {
        // Iterate in chunks
        int
            div = x1.Length / l,
            mod = x1.Length % l,
            i = 0,
            offset = 0;
        for (; i < div; i += 1, offset += l)
        {
            Vector<float>
                v1 = Unsafe.Read<Vector<float>>(px1 + offset),
                v1cmp = Vector.GreaterThan<float>(v1, cmp),
                v2 = Unsafe.Read<Vector<float>>(px2 + offset),
                v2cmp = Vector.GreaterThan<float>(v2, cmp);
            float*
                pcmp1 = (float*)Unsafe.AsPointer(ref v1cmp),
                pcmp2 = (float*)Unsafe.AsPointer(ref v2cmp);
            for (int j = 0; j < l; j++)
                if (pcmp1[j] == 0 != (pcmp2[j] == 0))
                    return false;
        }

        // Test the remaining items, if any
        if (mod == 0) return true;
        for (i = x1.Length - mod; i < x1.Length; i++)
            if (px1[i] > threshold != px2[i] > threshold)
                return false;
    }
    return true;
}

正如我所说,我已经使用 BenchmarkDotNet 测试了两个版本,并且使用了Vector<T>运行速度比另一台慢 3 倍左右。我尝试使用不同长度的跨度(从大约 100 到超过 2000)运行测试,但矢量化方法始终比另一种方法慢得多。

我在这里遗漏了一些明显的东西吗?

Thanks!

EDIT:我使用不安全代码并尝试在不并行化的情况下尽可能优化该代码的原因是该方法已经在Parallel.For迭代。

另外,具有在多个线程上并行化代码的能力通常并不是不优化各个并行任务的好理由。


我有同样的问题。解决方案是取消选中更喜欢 32 位项目属性中的选项。

SIMD 仅适用于 64 位进程。因此,请确保您的应用程序直接针对 x64,或者编译为任何 CPU 并且未标记为首选 32 位。[Source] https://devblogs.microsoft.com/dotnet/the-jit-finally-proposed-jit-and-simd-are-getting-married/

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

使用 Vector 的 SIMD 向量化 C# 代码运行速度比经典循环慢 的相关文章

  • 如何用另一个静态变量初始化一个静态变量?

    静态1 hpp include
  • ASP.NET MVC - 临时要求除一页之外的整个站点授权的简单方法

    我正在建立一个混合了公共页面和会员专用页面的网站 登录系统按原样工作正常 不过 我想启动一个封闭的 仅限邀请的预览 并暂时要求访问者登录才能执行除欢迎页面之外的所有操作 目前我有 Authorize 某些操作方法的属性 我也可以向其他操作方
  • 等待运算符错误

    我的代码有问题 我怎么解决这个问题 这个问题出现在await操作符中 public MyModel HttpClient client new HttpClient HttpResponseMessage response await cl
  • 提取单花括号内的值

    我想要一个收藏 value 一个字符串使用正则表达式 例如 lorem ipsum field1 lorem ipsum field2 lorem ipsum field1 lorem ipsum field2 field3 我会得到 fi
  • 使用 LINQ 展平嵌套字典

    所以我有一本形式的字典Dictionary
  • 微软怎么能说WinAPI中一个字的大小是16位呢?

    我刚刚开始学习WinAPI 在MSDN中 对WORD数据类型提供了以下解释 WORD16 位无符号整数 范围是十进制 0 到 65535 该类型在 WinDef h 中声明如下 typedef 无符号短 WORD 很简单 而且它与我一直在使
  • 将视频上传/保存到数据库或文件系统

    我以前从未尝试过保存视频 所以我对此了解不多 我知道如果视频很小 我可以转换为字节数组并保存到数据库 但是为了提高效率 我想了解如何将任何上传的视频保存到我的服务器文件中 然后只保存该文件的文件路径我的数据库表中的视频 我完全不知道如何开始
  • Web浏览器控件:如何捕获文档事件?

    我正在使用 WPF 的 WebBrowser 控件加载一个简单的网页 在这个页面上我有一个锚点或一个按钮 我想在我的应用程序后面的代码中 即在 C 中 捕获该按钮的单击事件 WebBrowser 控件是否有办法捕获加载页面元素上的单击事件
  • 编译器消息“警告:格式‘%s’需要类型‘char *’,但参数 2 具有类型‘char (*)’”

    我正在尝试运行一个简单的 C 程序 但收到此错误 警告 格式 s 需要类型 char 但参数 2 的类型为 char 20 我在跑步Mac OS X v10 8 https en wikipedia org wiki OS X Mounta
  • 是否自初始化 'A a = a;'允许吗?

    此代码在运行时在复制构造函数中失败 但编译器 MSVS2008 没有发出警告 您能解释一下 最好引用标准 这段代码是否非法或什么 我理解 A a a 永远不应该写在第一位 但我正在寻找理论背景 class A public A p new
  • 使用左连接获得不适当的输出

    我正在尝试获取变体列表 并且对于每个变体都获取所有subvariants list无论子变体属于何处 特别的Test say 100 这是示例数据 Id TestId SourceSubVariantId TargetSubVariantI
  • 如何解析多态 JSON 数组?

    我有一个 JSON 格式的文件 其中包含个人用户的记录 一些用户的记录中间有一个评论字段 我只想解析顶级项目 全名 贡献者姓名 电子邮件 使用 Newtonsoft JSON 解析器 但我似乎无法让它识别单个对象 当我将整个字符串解析为一个
  • ef core 在更新数据库期间不使用 ASPNETCORE_ENVIRONMENT

    我使用 Visual Studio 通过一定的迁移来更新我的所有环境 使用下面的命令效果很好 update database Migration initMigrationProduct c ProductContext Environme
  • 当一对迭代器初始化时,向量是否知道先保留?

    考虑以下代码 struct MyData MyData const BYTE pData size t uSize bucket pData pData uSize std vector
  • Rx 在不同的线程上生产和消费

    我试图通过此处的示例代码来简化我的问题 我有一个生产者线程不断地输入数据 并且我尝试在批次之间添加时间延迟来对其进行批处理 以便 UI 有时间渲染它 但结果并不如预期 生产者和消费者似乎在同一个线程上 我不希望批处理缓冲区在正在生成的线程上
  • 从 AuthorizeAttribute 继承的属性不起作用

    我目前正在尝试根据用户角色在新的 ASP MVC 5 应用程序中实现安全性 目标是防止用户在没有特定角色 或更高角色 的情况下访问某些控制器或控制器方法 根据到目前为止我所读到的问题 我创建了一个继承 AuthorizeAttribute
  • Selenium - 模式对话框存在 - 如何接受信息?

    我有以下问题 在页面上提交一些日期后 我有一个如图所示的模式对话框 我想单击 ENTER 来浏览该模式 但它不起作用 我有以下代码 driver FindElement By CssSelector input submit Click A
  • 如何使用实体框架设置连接字符串

    我将 EF6 与 MySQL 结合使用 并有一个用于多个数据库的模型 我希望能够在我的表单中设置连接设置 如何以编程方式设置模型的连接字符串 你应该使用EntityConnectionFactory这就是您所需要的 public strin
  • DbContext.SaveChangesAsync 异常处理

    当搭建新的脚手架时ApiController通过 Visual Studio 2013 中的异步操作和实体框架支持 某些方法可以包装DbContext SaveChangesAsync https msdn microsoft com en
  • 为什么 INT64_MIN 的定义不同?为什么他们的行为不同?

    The stdint h我公司的标题是 define INT64 MIN 9223372036854775808LL 但在我项目的一些代码中 一位程序员写道 undef INT64 MIN define INT64 MIN 92233720

随机推荐

  • Windows XP 上的 XamlParseException

    我有一个 WPF 应用程序 它在 vista 7 上运行得很好 但在 Windows XP 上它会抛出 System Windows Markup XamlParse 错误 这非常令人沮丧 因为我的应用程序中有很多控件 但我不这样做不知道是
  • 线程安全的多文件写入

    我有一个守护进程 它接受套接字连接并读取或写入一组动态文件 具体取决于连接的性质 因为我的守护进程是多线程的 所以存在同一个文件可能被多个线程写入的可能性 因为我的文件列表是动态的而不是固定的 所以我不确定如何防止一个线程碰撞另一个线程 出
  • 在多个 return 语句的情况下,使用 `std::move` 返回是否明智?

    我知道返回通常不是一个好主意std move i e bigObject foo bigObject result return std move result 而不是简单地 bigObject foo bigObject result r
  • 列数与计数器列性能

    我想知道获取特定列族中的列数的最佳方法是什么 我可以直接获取列数 但我不确定这是否是有效的解决方案 另一方面 我可以维护另一个列族 其中包含一个包含列数的计数器列 您有遇到类似问题的经验吗 http wiki apache org cass
  • Fortran函数解释

    我在 Fortran 中有这个函数 我正在尝试用 C 重新编码它 C C FUNCTION POLY C FUNCTION POLY N A X DIMENSION A N C POLY 0 L N DO 1 K 1 N POLY POLY
  • java.util.MissingResourceException:找不到基本名称消息的包,区域设置 en_US

    我是 JSF 的新手 正在尝试这段代码 这是我的 faces config xml
  • 如何动态更新Nifi中的variable.registry.properties?

    变量注册表属性是 Nifi 添加的一项功能 旨在促进软件开发生命周期 这意味着您可以在单独的开发环境中开发流程 并利用 nifi variable registry properties 属性中指定的自定义属性文件以及表达式语言来使用处理器
  • 如何对过滤后的 html 表求和?

    我有一个 HTML 表 我可以使用 jquery 过滤它 在表格的底部 我想要一个 总计 行 它将显示的所有值相加 总计 行中显示的总和应该是显示的所有行的总和 即不考虑隐藏行 我尝试添加一个条件 例如使求和取决于行的显示样式 但这没有成功
  • 为什么当 args 是序列时 subprocess.Popen 不起作用?

    当 args 参数作为序列给出时 我遇到了 subprocess Popen 问题 例如 import subprocess maildir home support Maildir 这有效 它打印 home support Maildir
  • 使用“optparse”模拟 Python 脚本的命令行参数?

    我想使用的 Python 脚本 称为snakefood http furius ca snakefood doc snakefood doc html 通常从命令行运行并采用命令行参数 例如 sfood path to my project
  • 如何指定 unicode 字符范围

    如何指定 Unicode 字符范围 空格 到 u00D7FF 我有一个正则表达式 例如r u0020 u00D7FF 并且它不会编译说这是一个糟糕的范围 我是 Unicode 正则表达式的新手 所以以前没有遇到过这个问题 有没有办法让这个编
  • swift 为 NSStream 创建字节缓冲区持有者

    in the Ray Wenderlich 套接字教程 http www raywenderlich com 3932 networking tutorial for ios how to create a socket based iph
  • Selenium 在 -browserSessionReuse 模式下启动新浏览器

    我正在尝试 browserSessionReuse Selenium 模式来加速我的测试 但我注意到了一个奇怪的行为 这种模式的目的是避免在测试之间浪费时间打开浏览器 这就是它的工作原理 但并非总是如此 如果我连续运行测试 它们就会在同一个
  • 禁用 VS 代码中的警告

    在此输入图像描述 https i stack imgur com KVDnO png 当我点击禁用 工作区 错误是 无法禁用扩展 ESLint 扩展 Node js 扩展包 依赖于此 还有什么其他方法可以消除反应本机错误 你需要定义 esl
  • ggplot 在函数中不起作用,以字符串形式传入变量名

    我有以下简单的功能 但它的 ggplot 命令不起作用 当从命令行给出该命令时 该命令可以正常工作 gt testfn lt function gdf first second library ggplot2 print ggplot gd
  • 包含 symfony2 的文件

    我正在使用 google Drive api 在 symfony2 中进行捆绑 我在 Utils 文件夹中有一个类 Authentication 它与 google 中的文件 我放入完全相同的文件夹中 进行交互 我想将这些文件包含在我的 A
  • 在 B 列中为 A 列中的相同值选择最小值 excel?

    我想得到例如第 1 列中相同值的第 2 列中的最小值或最大值 在我的示例中 我希望值 A 列 1 的列 2 的最大值为 18 而 B 的最大值为 27 我尝试过使用数组函数 但无法使其正常工作 敬请期待任何提示或解决方案 Example C
  • 如何从 web 应用程序运行量角器?

    我想运行一些量角器测试 针对 angularApp 为此 我创建了一个用户界面 提示用户输入脚本文件 然后我需要以某种方式让量角器启动并运行测试 我有哪些选择来实现这一目标 您可以将文件传递到后端 并保存它 然后后端像平常一样执行测试pro
  • 有没有办法在 IE 中获取边框半径和渐变背景?

    我想知道是否有任何使用 javascript 或其他方法让 IE 显示边框半径或渐变背景的解决方法 我在寻找在 IE9 中使用 渐变和边框半径 的修复时遇到了这个问题 是的 虽然您现在可以在 IE9 中同时使用两者 但遗憾的是您不能同时使用
  • 使用 Vector 的 SIMD 向量化 C# 代码运行速度比经典循环慢

    我看过几篇文章描述了如何Vector