GLSL除法与乘法的区别

4

假设我有这样的内容:

float foo;

float bar = baz / foo;
float qux = quux / foo;

当我执行以下操作时会发生什么:

foo = 1./foo;
float bar = baz * foo;    //can i expect roughly the same number as with division?
floar qux = quux * foo;   //is it always going to be faster?

鉴于WebGL可在各种硬件上运行,我是否可以期望在编译时会发生类似这样的情况,或者总是更安全地像这样编写代码?

同时也对此很好奇。

uniform float invFoo;
...
bar = baz * invFoo;
//instead of:
uniform float foo;
...
bar = baz / foo;

我不太理解这个

// A stupid compiler might use these as written: a divide, then add.
vec4 result1 = (value / 2.0) + 1.0;
vec4 result2 = (value / 2.0) - 1.0;
vec4 result3 = (value / -2.0) + 1.0;

// There are most likely converted to a single MAD operation (per line).
vec4 result1 = (value * 0.5) + 1.0;
vec4 result2 = (value * 0.5) - 1.0;
vec4 result3 = (value * -0.5) + 1.0;

在这种情况下,我不明白一个愚蠢的编译器要做什么。它是否遗漏了可以通过单个MAD指令完成此操作,或者它是否遗漏了可以将除法表达为乘法(同时遗漏了MAD)。

另外,如果移动一些内容并进行分组,会怎样:

vec2 foo,bar;
float baz;

baz = 1./baz;
vec2 temp = vec2( foo.x , bar.x ) * baz; //move but do one mult?
foo.x = temp.x;
bar.x = temp.y;
1个回答

3

我可以期望与除法大致相同的数字吗?

严格来说,不行:

$ cat a.cc
#include <iostream>

int main() {
    const float a = 1.40129846e-45f;
    const float b = a;

    std::cout << "b / a:       " << (b / a) << std::endl;
    std::cout << "b * (1 / a): " <<(b * (1.f / a)) << std::endl;

    return 0;
}
$ clang++ a.cc && ./a.out
b / a:       1
b * (1 / a): inf
$

然而,在更多或更少的真实生活示例中,乘法和除法可以给出接近的结果。其他任何情况都取决于您将使用结果的计算稳定性。如果这些计算不稳定(即,如果其中任何一个参数发生微小变化,则该计算结果会显着改变),则结果可能会有所不同。因此,您需要了解使用的值以及特别是您拥有的精度。GLSL浮点数并不总是32位IEEE浮点数,它们可能不够精确。
“它是否缺少单个MAD指令来完成,或者缺少可以将除法表示为乘法的内容(同时缺少MAD)。”
取决于特定编译器的特定怪癖,但可能是第二种情况。

谢谢回复。所以为了在MAD示例中保险起见,在大多数情况下,如果计算不是不稳定的,如果我有一个除法后面跟着一个加法,我应该计算倒数并进行乘法,这将很可能导致单个MAD,或者确定? - pailhead
你能否看一下最后的代码片段,我刚刚更新了它。 - pailhead
@pailhead 是的,那很可能会产生至少不慢的代码。你只需要确保这不会影响你的结果,例如通过尝试并检查渲染图像的质量是否发生了变化。 - Kirill Dmitrenko
@pailhead,通常情况下,尽可能使用向量操作是一个好的实践。但是,仅仅进行一次乘法,打包/解包的成本可能会超过收益。唯一的方法是测试,例如使用一些供应商工具或者只是使用EXT_disjoint_timer_query - Kirill Dmitrenko
谢谢!听起来最后一段代码可能过于冗长,而且可能没有任何好处。 - pailhead

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接