【发布时间】:2020-10-26 00:45:29
【问题描述】:
我有以下 C 函数,它在 GPU 上对 32 位无符号整数执行一些乘法和位移。假设我从值 X = 0 和 C = 2 开始:
void MWC64X_Step(global mwc64x_state_t *s)
{
uint X=s->x, C=s->c;
printf("X = %u, C = %u, ", X, C);
uint Xn=MWC64X_A*X+C;
uint carry=(uint)(Xn<C); //The (Xn<C) will be zero or one for scalar
uint Cn=mad_hi(MWC64X_A,X,carry);
printf("Xn = %u, Cn = %u, ", Xn, Cn);
s->x=Xn;
s->c=Cn;
}
与
typedef struct{ uint x; uint c; } mwc64x_state_t;
enum{ MWC64X_A = 4294883355U };
enum{ MWC64X_M = 18446383549859758079UL };
这个函数是我在网上找到的一个包的一部分。我很想知道 X 是否变得非常大,大约为 2^32,因为 Xn 被声明为无符号整数(在我的平台上为 32 位),那么它是如何计算的? Xn 只是保持模 MAX_INT_32 的值,还是执行一些其他操作?
我从 X=0 和 C=2 的几次连续运行中得到的结果:
Xn = 2, Cn = 0,
Xn = 4294799414, Cn = 1,
Xn = 1207281075, Cn = 4294715476. <--- 3rd iteration
谢谢,
【问题讨论】:
-
@kaylum,部分。我怀疑它通过使用模 2^32 进行翻转来计算乘法,但在我的示例中,我应该在上面的第三次迭代中得到 Xn=1207281664,而不是 1207281075。我不明白为什么!跨度>
-
你用的是什么编译器?
MWC64X_A和MWC64X_M的实际大小是多少?像printf( "sizeof( MWC64X_M ) = %zd\n", sizeof( MWC64X_M ) )这样的东西实际发出的大小。它们的实际值是多少?仅乘法的实际结果是什么? -
@AndrewHenle MWC64X_M 是 8 个字节,MWC64X_A 是 4 个字节。我在 LLVM clang 9 之上使用带有 CL1.2 的 OpenCL 编译器作为编译器。我对输入 (X= 4294799414, C=1) 的迭代得到的实际结果是 (Xn = 1207281075, Cn = 4294715476)
-
目前尚不清楚您如何认为应该在第三次迭代中获得 1207281664。我通过独立计算得到1207281075(见我的答案)。
标签: c integer-overflow unsigned-integer