【问题标题】:Why divide by 255 not faster 256 when converting OpenGL color gun uint8 to float? Is 1.0f rather than 0.996f for 255 crucial?为什么将OpenGL色枪uint8转换为浮点数时除以255而不是更快的256? 255 的 1.0f 而不是 0.996f 至关重要吗?
【发布时间】:2019-04-04 11:37:07
【问题描述】:

我正在研究大量利用 OpenGL 的渲染代码,这些代码将 COLORREF 转换为 float[3] 或 float[4],例如。 rgb[0] = ((float)GetRValue(col)) / 255.0f; 这给我敲响了性能警钟。 255.0f 显然可以是一个 int 但为什么不使用更快的除以 256 呢?

我们的首席图形程序员对这个建议表示反对,因为red = 255 除了 1.0f 之外的任何东西都是“道德错误的”,但是稍微降低浮点值的实际后果是什么?有什么可辨别的吗?

【问题讨论】:

  • "255.0f 显然可以是一个 int" 不,除非您想将所有值转换为 0,除了 255。"为什么不使用更快的除以 256?您需要在这里进行浮点除法,那么为什么您期望 256 更快?最后,你认为在使用 OpenGL 渲染 3D 场景时,颜色 int=>float 转换是一个瓶颈吗?
  • float/int 是 float 所以 100.0f/256 = .3906f ,而不是 0。我希望 float/256 比 float/255 快,因为优化器可以发现指数减少除法。
  • “瓶颈”很难定义,但由于这段代码是单线程的并且在 CPU 上,所以在毫无意义的精确数学上浪费时间似乎,嗯,毫无意义。

标签: opengl


【解决方案1】:

为什么不使用更快的 256 除法?

整数除以 256 会更快,但你没有做整数除法,是吗?浮点除法通常没有基于特定值的快捷方式。如果必须进行浮点除法,则需要支付浮点除法的费用。

This Godbolt example 表明 Clang 在高度优化时找不到使除以 256.0f 的速度比 255 快的方法。GCC 和 MSVC 确实得到了一个小的优化:它们用乘法代替除法而不是编译-time 计算值 1/256.0f,它是一个精确的浮点数。但是你可以通过让你的代码explicitly multiply by (1 / 255.0f) 来完成同样的事情,所以同样没有优势。

现在,理论上有更快的方法将无符号整数值标准化为浮点数。但这些通常依赖于对浮点值的直接位操作,并且可能实际上并不比仅仅进行浮点数学运算更快。您必须在您打算使用它们的特定情况下对其进行概要分析才能使其工作。


稍微降低浮点值的实际后果是什么?有什么可辨别的吗?

后果可能是任何事情。就现代 OpenGL 而言,您提供给 OpenGL 的每个值的含义完全由您的代码决定。实际上,您的代码可以添加除以 0.996 来重新调整数字,因此不会有真正的区别。

很容易编写一段着色器代码,如果您拒绝传递正确规范化的浮点值(任何执行if(value == 1.0f) 的操作,如果您正确执行规范化,则必须为真)。我可以很容易地编写不关心的代码。没有一般的答案;这一切都取决于你用它做什么。

兼容性 OpenGL 本质上是相同的方式:这完全取决于您使用它做什么。它可能是固定功能而不是着色器,但仍有足够的空间供您定义该数字的含义。

由于结果的可行性基于您在简单的normalizeIntegerToFloat 函数级别无法知道的信息,因此您应该为函数的调用者提供选择.提供准确的版本和有损版本。您绝对不应该做的是将有损版本设为默认值。如果函数的用户发现性能问题,他们可以切换到使用有损版本来帮助缓解问题。

【讨论】:

  • 我将浮点数除以编译时已知的 2 整数值的幂,并且有权期望优化器对其进行优化;例如用 float u8tofloat_trick(uint8_t x) { union { float f; uint32_t 我; } 你; u.f = 32768.0f; u.i |= x;返回 u.f - 32768.0f;当这种优化可用时,它在 amd64 上的 float/256 速度是 float/255 的两倍。我不必分析 FP 位操作来创建最佳代码;那是编译器的工作。我的工作是使用最适合优化的计算。
  • @IanBell:“时间是否最重要取决于你生成的代码。”如果它不是最重要的,你为什么要追求这个?聆听您的首席图形程序员的意见;你不应该从根本上改变数学运算的性质,除非它给你带来了重要的东西。值得一提的是,即使是我们这些“为游戏行业淘垃圾”的人不要这样做。
  • @IanBell:“任何包含 if(red==1.0) 的着色器都明显是可疑的” 为什么它是可疑的?谁来决定什么是“嫌疑人”,什么不是“嫌疑人”?着色器做数学;他们在内部做什么不关你的事;您的工作是为其提供正确的数据。针对 1.0 的测试,对于从标准化纹理中获取的值,并非不合理。您有时会在查看颜色的 alpha 值时看到它,这是一个更具体的示例。完全不透明和不透明之间的区别非常显着。
  • @IanBell:“它给我的印象是一种安全、简单且没有缺点的优化”我已经证明它实际上并没有使代码更快,所以它不是“优化”、“安全、简单”或其他。它是否“没有缺点”完全取决于值如何使用,这可能不在您的控制之下。因此,只有当您认为某些优化不会提高性能并且您将任何中断的代码定义为“可疑”时,您的陈述才是正确的。但如果你只想强化自己的信念,何必问这个问题呢?
  • @NicholBolas。 “你测试你给出的值,这些值是基于确切的数字,而不是某些计算的结果。”这是假设性的。
猜你喜欢
  • 1970-01-01
  • 2021-08-03
  • 1970-01-01
  • 2011-02-13
  • 1970-01-01
  • 2010-11-18
  • 1970-01-01
  • 1970-01-01
  • 2019-02-27
相关资源
最近更新 更多