两个单精度浮点向量的点积在 CUDA 内核中与在主机上产生不同的结果

2023-12-26

在调试一些 CUDA 代码时,我使用以下方法与等效的 CPU 代码进行比较printf陈述,并注意到在某些情况下我的结果有所不同;它们在任何一个平台上都不一定是错误的,因为它们在浮点舍入误差之内,但我仍然有兴趣知道是什么导致了这种差异。

我能够将问题追溯到不同的点积结果。在 CUDA 和主机代码中,我都有向量 a 和 b 类型float4。然后,在每个平台上,我使用以下代码计算点积并打印结果:

printf("a: %.24f\t%.24f\t%.24f\t%.24f\n",a.x,a.y,a.z,a.w);
printf("b: %.24f\t%.24f\t%.24f\t%.24f\n",b.x,b.y,b.z,b.w);
float dot_product = a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w;
printf("a dot b: %.24f\n",dot_product);

CPU 的打印结果为:

a: 0.999629139900207519531250   -0.024383276700973510742188 -0.012127066962420940399170 0.013238593004643917083740
b: -0.001840781536884605884552  0.033134069293737411499023  0.988499701023101806640625  1.000000000000000000000000
a dot b: -0.001397025771439075469971

对于 CUDA 内核:

a: 0.999629139900207519531250   -0.024383276700973510742188 -0.012127066962420940399170 0.013238593004643917083740
b: -0.001840781536884605884552  0.033134069293737411499023  0.988499701023101806640625  1.000000000000000000000000
a dot b: -0.001397024840116500854492

正如您所看到的,a 和 b 的值在两个平台上似乎按位等效,但完全相同的代码的结果却略有不同。据我了解,浮点乘法是根据 IEEE 754 标准明确定义的,并且与硬件无关。然而,对于为什么我没有看到相同的结果,我确实有两个假设:

  1. 编译器优化是对乘法进行重新排序,它们在 GPU/CPU 上以不同的顺序发生,从而产生不同的结果。
  2. CUDA 内核使用融合乘加 (FMA) 运算符,如中所述http://developer.download.nvidia.com/assets/cuda/files/NVIDIA-CUDA-Floating-Point.pdf http://developer.download.nvidia.com/assets/cuda/files/NVIDIA-CUDA-Floating-Point.pdf。在这种情况下,CUDA 结果实际上应该更准确一些。

除了将 FMUL 和 FADD 合并到 FMA 之外(可以使用 nvcc 命令行开关关闭)-fmad=false),CUDA编译器遵守C/C++规定的求值顺序。根据 CPU 代码的编译方式,它可能会使用比单精度更宽的精度来累积点积,然后产生不同的结果。

对于 GPU 代码,将 FMUL/FADD 合并到 FMA 中是很常见的情况,因此产生的数值差异也很常见。出于性能原因,CUDA 编译器执行积极的 FMA 合并。使用 FMA 通常还会产生更准确的结果,因为舍入步骤的数量减少了,并且由于 FMA 在内部维护全角乘积,因此可以防止减法抵消。我建议阅读以下白皮书及其引用的参考文献:

https://developer.nvidia.com/sites/default/files/akamai/cuda/files/NVIDIA-CUDA-Floating-Point.pdf https://developer.nvidia.com/sites/default/files/akamai/cuda/files/NVIDIA-CUDA-Floating-Point.pdf

为了让 CPU 和 GPU 结果匹配健全性检查,您需要在 GPU 代码中关闭 FMA 合并:-fmad=false,并在 CPU 上强制每个中间结果以单精度存储:

   volatile float p0,p1,p2,p3,dot_product; 
   p0=a.x*b.x; 
   p1=a.y*b.y; 
   p2=a.z*b.z; 
   p3=a.w*b.w; 
   dot_product=p0; 
   dot_product+=p1; 
   dot_product+=p2; 
   dot_product+=p3;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

两个单精度浮点向量的点积在 CUDA 内核中与在主机上产生不同的结果 的相关文章

  • 在 C# 中创建具有单独列的分隔文本

    我一直在尝试在 C 中创建一个制表符限制的文本文件 以便数据正确显示在单独的列中 Firstname Lastname Age John Smith 17 James Sawyer 31 我尝试过 t 字符 但我得到的只是 Firstnam
  • 如何使用MemoryCache代替Timer来触发一个方法?

    以下方法通过等待已运行操作的结果来处理并发请求 对数据的请求可能会使用相同 不同的凭据同时出现 对于每组唯一的凭据 最多可以有一个GetCurrentInternal呼叫正在进行中 当准备就绪时 该呼叫的结果将返回给所有排队的服务员 pri
  • 启动时出现 OData v4 错误:找不到段“Whatever”的资源

    我正在构建新的 v4 服务 一切进展顺利 直到我为新模型 实体添加了新控制器 并在启动站点进行测试运行时收到此错误 控制器似乎编码正确 就像其他控制器一样 控制器 CustomersOData 中的操作 GetFeed 上的路径模板 Cus
  • 确定 C/C++ 中的浮点运算是否发生舍入

    我正在尝试提出一种有效的方法来确定 IEEE 754 操作何时将 确实发生舍入 不幸的是我无法简单地检查硬件标志 它必须在几个不同的平台上运行 我想到的方法之一就是以不同的舍入模式进行运算来比较结果 添加示例 double result o
  • 推导指南中的引用和值之间的差异

    考虑类型A template
  • 如何为 C 分配的 numpy 数组注册析构函数?

    我想在 C C 中为 numpy 数组分配数字 并将它们作为 numpy 数组传递给 python 我可以做的PyArray SimpleNewFromData http docs scipy org doc numpy reference
  • 在 Unity 进程和另一个 C# 进程之间进行本地 IPC 的最快方法 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我希望每秒大约 30 次从 C 应用程序向我的 Unity 应用程序传送大量数据 由于 Unity 不支持映射内存和管道 我考虑了 t
  • C++中的类查找结构体数组

    我正在尝试创建一个结构数组 它将输入字符串链接到类 如下所示 struct string command CommandPath cPath cPathLookup set an alarm AlarmCommandPath send an
  • 无法在 Windows 运行时组件库的 UserControl 中创建依赖项属性

    我想在用户控件内创建数据可绑定属性 这个用户控件包含一个 Windows 运行时组件 项目 我使用下面的代码来创建属性 public MyItem CurrentItem get return MyItem GetValue Current
  • 关于在 Windows 上使用 WiFi Direct Api?

    我目前正在开发一个应用程序 我需要在其中创建链接 阅读 无线网络连接 在桌面应用程序 在 Windows 10 上 和平板电脑 Android 但无关紧要 之间 工作流程 按钮 gt 如果需要提升权限 gt 创建类似托管网络的 WiFi 网
  • 在一个字节中存储 4 个不同的值

    我有一个任务要做 但我不知道从哪里开始 我不期待也绝对不想要代码中的答案 我想要一些关于该怎么做的指导 因为我感到有点失落 将变量打包和解包到一个字节中 您需要在一个字节中存储 4 个不同的值 这些值为 NAME RANGE BITS en
  • 上下文敏感与歧义

    我对上下文敏感性和歧义如何相互影响感到困惑 我认为正确的是 歧义 歧义语法会导致使用左推导或右推导构建多个解析树 所有可能的语法都是二义性的语言是二义性语言 例如 C 是一种不明确的语言 因为 x y 总是可以表示两个不同的事物 如下所述
  • Python 中的十进制到二进制半精度 IEEE 754

    我只能使用以下命令将十进制转换为二进制单精度 IEEE754struct pack模块 或者使用相反的方法 float16 或 float32 numpy frombuffer 是否可以使用 Numpy 将十进制转换为二进制半精度浮点数 我
  • (de)从 CSV 序列化为对象(或者最好是类型对象的列表)

    我是一名 C 程序员 试图学习 C 似乎有一些内置的对象序列化 但我在这里有点不知所措 我被要求将测试数据从 CSV 文件加载到对象集合中 CSV 比 xml 更受青睐 因为它更简单且更易于人类阅读 我们正在创建测试数据来运行单元测试 该集
  • gcc 的配置选项如何确定默认枚举大小(短或非短)?

    我尝试了一些 gcc 编译器来查看默认枚举大小是否很短 至少一个字节 强制使用 fshort enums 或无短 至少 4 个字节 强制使用 fno short enums user host echo Static assert 4 si
  • 有没有办法强制显示工具提示?

    我有一个验证字段的方法 如果无法验证 该字段将被清除并标记为红色 我还希望在框上方弹出一个工具提示 并向用户显示该值无效的消息 有没有办法做到这一点 并且可以控制工具提示显示的时间 我怎样才能让它自己弹出而不是鼠标悬停时弹出 If the
  • 英特尔 Pin 与 C++14

    问题 我有一些关于在 C 14 或其他 C 版本中使用英特尔 Pin 的问题 使用较新版本从较旧的 C 编译代码很少会出现任何问题 但由于 Intel Pin 是操作指令级别的 如果我使用 C 11 或 C 14 编译它 是否会出现任何不良
  • memset 未填充数组

    u32 iterations 5 u32 ecx u32 malloc sizeof u32 iterations memset ecx 0xBAADF00D sizeof u32 iterations printf 8X n ecx 0
  • 使用 GROUP 和 SUM 的 LINQ 查询

    请帮助我了解如何使用带有 GROUP 和 SUM 的 LINQ 进行查询 Query the database IEnumerable
  • 如何将 Roslyn 语义模型返回的类型符号名称与 Mono.Cecil 返回的类型符号名称相匹配?

    我有以下代码 var paramDeclType m semanticModel GetTypeInfo paramDecl Type Type Where paramDeclType ToString returns System Col

随机推荐

  • React hooks useState 不随 onChange 更新[重复]

    这个问题在这里已经有答案了 更新的问题 如果我在滚动之前在输入字段中输入一些内容expandedprop 被设置为 true 正确 如果我向下滚动 扩展设置为 false 正确 如果我现在在输入字段中输入一些内容expanded还是fals
  • 在 IntelliJ 中同时推送到多个远程存储库

    我正在使用 gitIntelliJ IDEA 集成开发环境 https www jetbrains com idea 我有两个远程存储库 我想将我的提交推送到其中 如何同时推送到两个遥控器 有一个不错的博客文章 https www xeno
  • 如何从我的应用程序中检查比特币地址余额?

    假设在 Java 应用程序 或任何其他语言 中 如何检查比特币地址 任何地址 不一定是我的地址 的余额 我需要一个像上面那样的功能区块链信息 https blockchain info or 比特易网 http www biteasy co
  • 如何在intellij idea IDE中运行javafx应用程序

    我正在尝试运行 JavaFX 应用程序 但显示以下错误 错误 缺少 JavaFX 运行时组件 并且需要运行该应用程序 直到这一步 我无法导入JavaFX 并且我已经从 usr lib jvm java 8 openjdk amd64 完成了
  • 如何解决 SSIS 包中 OLE DB 目标中的非空约束?

    I m new to SSIS Package I want to transfer data from source to destination database which has different table structures
  • 为单个用户设置默认 PASE IBM i shell

    The PASE http www 01 ibm com support knowledgecenter ssw ibm i 72 rzalf rzalfintro htm lang en环境默认提供并使用 korn shell 这ibmp
  • Phonegap Android 无法上网

    我正在 Phonegap 中编写我的第一个应用程序 并且我一直在 Android 设备上对其进行测试 我相信我已授予适当的许可
  • C++ 构造函数/析构函数继承

    编辑 答案摘要 下面B是A的子类 这是一个术语问题 ctors 和 dtors 是not继承 从某种意义上说 B 的 ctor dtor 将not借用A的接口 一个类至少有一个构造函数 并且只有一个析构函数 Constructors B 不
  • OpenCV (c++) 多通道元素访问

    我正在尝试使用 新 OpenCV 2 0 c 版本 但其他一切都像简单的 C 版本一样 我在更改图像中的值时遇到一些问题 该图像是 CV 8UC3 for int i 0 i
  • 带 keycloak 的 Flask-OIDC - oidc_callback 默认回调不起作用

    我正在尝试在一个简单的 Flask 应用程序中使用 Flask oidc 以便通过 keycloak 添加身份验证 但是 一旦我使用有效凭据登录 它就会返回到不存在的 oidc callback Flask 日志显示了很多带有 302 结果
  • 多重继承的接口是否冗余?

    这不是关于抽象类和接口之间差异的另一个问题 因此请在投票关闭它之前三思而后行 我知道接口对于那些不支持多重继承的 OOP 语言 例如 C 和 Java 至关重要 但那些呢with多重继承 在具有多重继承的语言中 接口的概念 作为特定的语言功
  • 通过模板参数给定其长度,在编译时生成相同类型的 std::tuple

    在 C 中 如何实现带有指示元组长度的 int 模板参数的函数并生成具有该长度的 std tuple E g func lt 2 gt returns std tuple
  • 闪亮应用程序的 renderDataTable 中的列宽度,无需拉伸

    我想要一个数据表 及其所有排名 搜索和页面功能 它不会完全延伸到整个页面 并导致每列中有大量空白 理想情况下 列宽类似于 wrap 样式renderTable 我知道我可以修复相对列宽 但是 我的表将根据所选输入动态更新不同数量的列 我希望
  • 使用 FMOD 将输出保存到磁盘

    我正在使用 FMOD 播放一些声音 我想将生成的混音保存到磁盘 我一直在尝试 system gt recordStart 0 sound true 路径 但这保存了设备的麦克风输入 以某种方式 我想将扬声器输出重定向到磁盘 谢谢 Marc
  • XML 架构 - “此上下文中不支持元素”

    我的代码中的最后内容有问题 它说 http www w3 org 2001 XMLSchema http www w3 org 2001 XMLSchema 在这种情况下不支持 我该如何解决这个问题 问题截图
  • d3:Multi-Foci Force关键代码组件理解

    多焦点力的真正魔力就在这里完成 function tick e var k 1 e alpha Push nodes toward their designated focus nodes forEach function o i o y
  • 使用 Java JSch 确定来自 SFTP 服务器的最新文件

    有没有办法使用 Java JSch 确定 Unix SFTP 服务器上最新文件的名称 我想将最新文件从服务器复制到本地计算机 我已经有一个工作代码了 但我无法识别最新的文件 该文件夹包含许多以下格式的文件 Some Report dd MM
  • ios7 CameraPickerController 相机中的图像被冻结

    我有一个简单的相机视图控制器代码 UIImagePickerController picker new UIImagePickerController picker PrefersStatusBarHidden picker SourceT
  • 如何使用 JSF 显示/隐藏组件?

    如何使用 JSF 显示 隐藏组件 我目前正在尝试在 javascript 的帮助下做同样的事情 但没有成功 我无法使用任何第三方库 谢谢 阿比 你实际上可以做到这一点withoutJavaScript 仅使用 JSFrendered属性 通
  • 两个单精度浮点向量的点积在 CUDA 内核中与在主机上产生不同的结果

    在调试一些 CUDA 代码时 我使用以下方法与等效的 CPU 代码进行比较printf陈述 并注意到在某些情况下我的结果有所不同 它们在任何一个平台上都不一定是错误的 因为它们在浮点舍入误差之内 但我仍然有兴趣知道是什么导致了这种差异 我能