避免调用 Floor()

2024-01-12

我正在编写一段代码,需要处理不一定在 0 到 1 范围内的 uvs(2D 纹理坐标)。例如,有时我会得到 u 分量为 1.2 的 uv。为了解决这个问题,我正在实现一个包装,通过执行以下操作来导致平铺:

u -= floor(u)
v -= floor(v)

这样做会使 1.2 变成 0.2,这是所需的结果。它还可以处理负面情况,例如 -0.4 变为 0.6。

然而,这些对发言权的调用相当慢。我已经使用 Intel VTune 分析了我的应用程序,并且我花费了大量的周期来执行此底层操作。

在对这个问题进行了一些背景阅读之后,我提出了以下函数,该函数速度更快一些,但仍然有很多不足之处(我仍然会受到类型转换惩罚等)。

int inline fasterfloor( const float x ) { return x > 0 ? (int) x : (int) x - 1; }

我已经看到了一些通过内联汇编完成的技巧,但似乎没有任何东西可以完全正确地工作或有任何显着的速度改进。

有谁知道处理这种情况的任何技巧?


老问题,但我遇到了它,这让我有点抽搐,因为它还没有得到令人满意的答案。

TL;DR:*不要**为此使用内联汇编、内在函数或任何其他给定的解决方案!相反,使用快速/不安全的数学优化进行编译(g++ 中的“-ffast-math -funsafe-math-optimizations -fno-math-errno”)。 Floor() 如此慢的原因是,如果转换溢出(FLT_MAX 不适合任何大小的标量整数类型),它会更改全局状态,这也使得向量化变得不可能,除非禁用严格的 IEEE-754 兼容性,无论如何你可能不应该依赖它。使用这些标志进行编译会禁用问题行为。

一些备注:

  1. 带有标量寄存器的内联汇编不可矢量化,这会极大地抑制优化编译时的性能。它还要求当前存储在向量寄存器中的任何相关值溢出到堆栈并重新加载到标量寄存器中,这违背了手动优化的目的。

  2. 在我的机器上,使用 SSE cvttss2si 和您概述的方法进行内联汇编实际上比带有编译器优化的简单 for 循环慢。 这可能是因为如果您允许编译器将整个代码块矢量化在一起,那么您的编译器将分配寄存器并更好地避免管道停顿。对于像这样的一小段代码,内部依赖链很少,几乎没有寄存器溢出的可能性,它几乎没有机会比由 asm() 包围的手工优化代码做得更糟。

  3. 内联汇编不可移植,在 Visual Studio 64 位版本中不受支持,并且极其难以阅读。内在函数也有与上面列出的相同的警告。

  4. 所有其他列出的方法都是不正确的,这可以说比缓慢更糟糕,并且它们在每种情况下都给出了这样的边际性能改进,以至于它不能证明该方法的粗糙性是合理的。 (int)(x+16.0)-16.0 太糟糕了,我什至都不会碰它,但你的方法也是错误的,因为它给了 Floor(-1) 作为-2。当数学代码对性能至关重要以至于标准库无法为您完成这项工作时,在数学代码中包含分支也是一个非常糟糕的主意。所以你的(不正确的)方式应该看起来更像 ((int) x) - (x

  5. 我尝试使用按位转换和通过位掩码舍入,就像 SUN 的 newlib 实现在 fmodf 中所做的那样,但它需要很长时间才能正确,并且在我的机器上慢了好几倍,即使没有相关的编译器优化标志。很可能,他们为某些古老的 CPU 编写了该代码,其中浮点运算相对非常昂贵,并且没有矢量扩展,更不用说矢量转换操作了; AFAIK 在任何常见架构上都不再出现这种情况。 SUN 也是 Quake 3 使用的快速逆 sqrt() 例程的诞生地;现在大多数架构上都有相关的说明。微优化的最大陷阱之一是它们很快就会过时。

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

避免调用 Floor() 的相关文章

  • 计算 XML 中特定 XML 节点的数量

    请参阅此 XML
  • 适合初学者的良好调试器教程[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 有谁知道一个好的初学者教程 在 C 中使用调试器 我感觉自己好像错过了很多 我知道怎么做 单步执行代码并查看局部变量 虽然这常常给我带来问
  • GetType() 在 Type 实例上返回什么?

    我在一些调试过程中遇到了这段代码 private bool HasBaseType Type type out Type baseType Type originalType type GetType baseType GetBaseTyp
  • ComboBox DataBinding 导致 ArgumentException

    我的几个类对象 class Person public string Name get set public string Sex get set public int Age get set public override string
  • 查找进程的完整路径

    我已经编写了 C 控制台应用程序 当我启动应用程序时 不使用cmd 我可以看到它列在任务管理器的进程列表中 现在我需要编写另一个应用程序 在其中我需要查找以前的应用程序是否正在运行 我知道应用程序名称和路径 所以我已将管理对象搜索器查询写入
  • JNI 将 Char* 2D 数组传递给 JAVA 代码

    我想从 C 代码通过 JNI 层传递以下指针数组 char result MAXTEST MAXRESPONSE 12 12 8 3 29 70 5 2 42 42 在java代码中我写了以下声明 public static native
  • 如何填充 ToolStripComboBox?

    我发现它很难将数据绑定到ToolStripComboBox 好像没有这个ValueMember and DisplayMember特性 怎么绑定呢 访问toolstripcombobox中包装的组合框并访问其ValueMember Disp
  • 为什么在 WebApi 上下文中在 using 块中使用 HttpClient 是错误的?

    那么 问题是为什么在 using 块中使用 HttpClient 是错误的 但在 WebApi 上下文中呢 我一直在读这篇文章不要阻止异步代码 https blog stephencleary com 2012 07 dont block
  • unordered_map 中字符串的 C++ 哈希函数

    看起来 C 标准库中没有字符串的哈希函数 这是真的 在任何 c 编译器上使用字符串作为 unordered map 中的键的工作示例是什么 C STL提供模板专业化 http en cppreference com w cpp string
  • File.AppendText 尝试写入错误的位置

    我有一个 C 控制台应用程序 它作为 Windows 任务计划程序中的计划任务运行 此控制台应用程序写入日志文件 该日志文件在调试模式下运行时会创建并写入应用程序文件夹本身内的文件 但是 当它在任务计划程序中运行时 它会抛出一个错误 指出访
  • 使用 LINQ to SQL 时避免连接超时的最佳实践

    我需要知道在 net 应用程序中使用 LINQ to SQL 时避免连接超时的最佳实践 特别是在返回时IQueryable
  • 为什么可以通过ref参数修改readonly字段?

    考虑 class Foo private readonly string value public Foo Bar ref value private void Bar ref string value value hello world
  • 如何在 Qt 应用程序中通过终端命令运行分离的应用程序?

    我想使用命令 cd opencv opencv 3 0 0 alpha samples cpp cpp example facedetect lena jpg 在 Qt 应用程序中按钮的 clicked 方法上运行 OpenCV 示例代码
  • 如何在 C 中安全地声明 16 位字符串文字?

    我知道已经有一个标准方法 前缀为L wchar t test literal L Test 问题是wchar t不保证是16位 但是对于我的项目 我需要16位wchar t 我还想避免通过的要求 fshort wchar 那么 C 不是 C
  • 为什么我的单选按钮不起作用?

    我正在 Visual C 2005 中开发 MFC 对话框应用程序 我的单选按钮是 m Small m Medium 和 m Large 它们都没有在我的 m Summary 编辑框中显示应有的内容 可能出什么问题了 这是我的代码 Pizz
  • 在屏幕上获取字符

    我浏览了 NCurses 函数列表 似乎找不到返回已打印在屏幕上的字符的函数 每个字符单元格中存储的字符是否有可访问的值 如果没有的话Windows终端有类似的功能吗 我想用它来替换屏幕上某个值的所有字符 例如 所有a s 具有不同的特征
  • 使 Guid 属性成为线程安全的

    我的一个类有一个 Guid 类型的属性 该属性可以由多个线程同时读写 我的印象是对 Guid 的读取和写入不是原子的 因此我应该锁定它们 我选择这样做 public Guid TestKey get lock testKeyLock ret
  • 可访问性不一致:参数类型的可访问性低于方法

    我试图在两个表单之间传递一个对象 基本上是对当前登录用户的引用 目前 我在登录表单中有一些类似的内容 private ACTInterface oActInterface public void button1 Click object s
  • Objective-C / C 给出枚举默认值

    我在某处读到过关于给枚举默认值的内容 如下所示 typedef enum MarketNavigationTypeNone 0 MarketNavigationTypeHeirachy 1 MarketNavigationTypeMarke
  • 如何将十六进制字符串转换为无符号长整型?

    我有以下十六进制值 CString str str T FFF000 如何将其转换为unsigned long 您可以使用strtol作用于常规 C 字符串的函数 它使用指定的基数将字符串转换为 long long l strtol str

随机推荐

  • 通过链接克服云代码解析限制 1000?

    我有以下函数 我用它来确定用户在记分牌中的排名 Parse Cloud define getUserGlobalRank function request response var usernameString request params
  • 如何从网格中检查复选框获取详细信息?

    我有EditorGridPanel 网格的ColumnModel包括TextField ComboBox和CheckBox 编辑 TextField 或 ComboBox 后 将触发 afteredit 事件 其中包含有关已编辑字段的详细信
  • 使用 es6 进行 chrome 调试

    我正在尝试在我的项目中使用 Ecmascript 2015 但我发现很难在特定位置添加断点 我认为设置断点是合乎逻辑的位置 我在 chrome 中将 enable javascript harmony 标志设置为 true 如果有帮助 但我
  • 如何使用 MiniTest 测试记录器消息?

    我有一个应用程序 我想测试我是否正确 来自我的记录器的消息 一个简短的示例 您可以在 log4r 和 logger 之间切换 gem minitest require minitest autorun require log4r requi
  • 共享首选项中的数据缓存

    我的应用程序中有 2 个进程 从一个进程我将数据保存到SharedPreferences 从第二个过程 检索 当我检索数据时 我收到SharedPreferences使用旧数据 我检查 xml 文件 发现当前文件中的数据和收到的数据不同 看
  • 在 GO 中使用 RSA-SHA 进行签名和解码

    我正在尝试签署一个字符串 然后用公钥验证它 我的验证结果为空 我究竟做错了什么 package main import crypto crypto rand crypto rsa crypto sha256 crypto x509 enco
  • 如何在 SwiftUI macOS 中创建急救人员

    我正在尝试制作我的文本字段 NSViewRepresentable包裹NSTextField 出现时的第一个响应者 我已经测试了很多答案thread https stackoverflow com questions 56507839 sw
  • 使用 VBA 隐藏数据透视表

    如何使用 VBA 隐藏数据透视表 我尝试访问 PivotTables index Visible 但没有Visible财产为PivotTable目的 如果用户更改某些复选框 我需要隐藏这些数据透视表 也许我可以将它们隐藏在白盒子后面 但在我
  • 如何将 ListItemCollection (dropdownlist.items) 转换为字典

    如何转换ListItemCollection DropDownList items to a Dictionary
  • 如何使用 IMAP 和 PHP 保存电子邮件中的图像附件?

    我已经成功编写了连接到我的邮件服务器并检索所有新邮件的标头和正文的脚本 我想更进一步检测附件是否存在 仅图像 如果存在 则下载到服务器 如何使用 PHP 和 IMAP 来实现这一点 提前致谢 KimNyholm 发布了一组 imap 客户端
  • 使用 ffmpeg 逐帧写入视频

    我正在尝试使用 ffmpeg 逐帧编写视频 如下所述 http zulko github io blog 2013 09 27 read and write video frames in python using ffmpeg http
  • 转换 Spark 数据框中的日期模式

    我在 Spark 数据框中有一列字符串数据类型 日期采用 yyyy MM dd 模式 我想以 MM dd yyyy 模式显示列值 我的数据是 val df sc parallelize Array steak 1990 01 01 2000
  • 如何使用 python 从 xml 中提取特定数据?

    我对 python 比较陌生 我一直在尝试通过实践方法学习Python 我通过做euler项目学习了c c 现在我正在学习如何从文件中提取数据 我已经掌握了从简单文本文件中提取数据的窍门 但我有点陷入 xml 文件中 我试图做的一个例子 我
  • Django -vs- Grails -vs-?

    我想知道是否有类似 Django 的简单 Web 应用程序开发与良好的部署 调试和其他工具相结合 Django 是一个非常高效的框架 用于构建内容丰富的网站 与 Java 中的一些怪物相比 这是我尝试过的最好的 呼吸新鲜空气 然而它是用 P
  • 用地址而不是数字填充队列

    我想知道是否可以将地址而不是其内容推送到队列中 例如 我有一个二维数组 我正在围绕它移动 我想记录我去过的地方 但我不一定关心这些地方的内容 是的 您只需将队列声明为指针队列 例如 int 或您正在使用的任何类型 这是代码 include
  • 如果浮点范围更大,通过浮点的往返是否始终定义行为?

    假设我有两种算术类型 一种是整数类型 I 和一个浮点数 F 我还假设std numeric limits i max 小于std numeric limits i
  • 更新现有的 Yaml 文件

    我想更新我现有的user yaml文件而不擦除其他对象或属性 我已经用谷歌搜索了两天寻找解决方案 但没有运气 实际输出 name Test User age 30 address line1 My Address Line 1 line2
  • M1 MBP Rails db:create 引发 msgpack 错误

    您好 我是 Ruby on Rails 新手 当我跑步时rails db create 在M1 MBP上运行时出现以下错误 Library Ruby Gems 2 6 0 gems msgpack 1 4 2 lib msgpack rb
  • (简单)允许 24:00:00 和 00:00:00 作为输入的日期格式

    我已经寻找这个有一段时间了 到目前为止还没有成功 你知道是否有一个 DateFormat 这样的类 它允许我使用 00 00 00 和 24 00 00 作为输入参数 它们都是午夜 但是当调用 getHour 时 结果我会得到 0 或 24
  • 避免调用 Floor()

    我正在编写一段代码 需要处理不一定在 0 到 1 范围内的 uvs 2D 纹理坐标 例如 有时我会得到 u 分量为 1 2 的 uv 为了解决这个问题 我正在实现一个包装 通过执行以下操作来导致平铺 u floor u v floor v