在 32 位运算的机器上,将存储在 2 个 uint32 中的 8 字节除以一个 uint32

问题描述 投票:0回答:1

我想在 WebGPU 中将 uint64 除以 uint32,目前 WebGPU 只处理 uint32 操作。因此,我尝试通过将 long 存储到两个 uint32 缓冲区

high
low
来模拟这一点。现在我想将它们除以 uint32
b

我看到了这个答案,但我很难复制它。我认为要使其起作用,我应该这样做 (A / Y)x3 + (((A % Y)x + B) / Y)x2 + (((((A % Y)x + B) % Y) x + C) / Y)x + ((((((A % Y)x + B) % Y)x + C) / Y)x + D) / Y 其中 x 为 2^16。这样,A是

high
的前16位,B是
high
的最低16位。同样,C 是
low
的前 16 位,D 是
low
的后 16 位。

这是该算法的 C 代码:

void u64DivU32(uint32_t& low, uint32_t& high, uint32_t& b, uint32_t& res_low, uint32_t& res_high) {
    uint32_t a, b, c, d;

    a = high >> 16;
    b = (high << 16) >> 16;
    c = (low >> 16);
    d = (low << 16) >> 16;


    // compute high
    uint32_t t0 = a; // A
    uint32_t t1 = (((t0 % b) << 16) + b); // ((A % Y)x + B)
    // (A / Y)x3 + (((A % Y)x + B) / Y)x2 
    res_high = ((t0 / b) << 16) + (t1/b);

    // compute low
    uint32_t t2 = (((t1 % b) << 16) + c); // (((((A % Y)x + B) % Y)x + C) / Y)x
    uint32_t t3 = (((t2 / b) << 16) + d); // ((((((A % Y)x + B) % Y)x + C) / Y)x + D) / Y
    res_low = ((t2 / b) << 16) + (t3/b);
}

然而,并没有成功。经过几次测试,

res_high
按预期工作,但
res_low
始终处于关闭状态。我也不确定当 b 大于 65535 时如何正确应用它

32-bit integer-division webgpu wgsl
1个回答
0
投票

我看到两个问题。 首先,您重复使用了

b
,但这一定是在输入问题时才使用的,因为您无法接近。

第二个错误是你在计算

t3
时输入了 / 而不是 %

void u64DivU32(uint32_t& low, uint32_t& high, uint32_t& divisor, uint32_t& res_low, uint32_t& res_high) {
    uint32_t a, b, c, d;

    a = high >> 16;
    b = (high << 16) >> 16;
    c = (low >> 16);
    d = (low << 16) >> 16;


    // compute high
    uint32_t t0 = a; // A
    uint32_t t1 = (((t0 % divisor) << 16) + b); // ((A % Y)x + B)
    // (A / Y)x3 + (((A % Y)x + B) / Y)x2 
    res_high = ((t0 / divisor) << 16) + (t1/divisor);

    // compute low
    uint32_t t2 = (((t1 % divisor) << 16) + c); 
    uint32_t t3 = (((t2 % divisor) << 16) + d); 
    res_low = ((t2 / divisor) << 16) + (t3/divisor);
}
© www.soinside.com 2019 - 2024. All rights reserved.