gpt4 book ai didi

c++ - boost::random::uniform_real_distribution 应该在处理器之间相同吗?

转载 作者:太空狗 更新时间:2023-10-29 20:23:18 24 4
gpt4 key购买 nike

以下代码在 x86 32 位和 64 位处理器上产生不同的输出。

应该是这样的吗?如果我将它替换为 std::uniform_real_distribution 并使用 -std=c++11 进行编译,它会在两个处理器上产生相同的输出。

#include <iostream>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/uniform_real_distribution.hpp>

int main()
{
boost::mt19937 gen;
gen.seed(4294653137UL);
std::cout.precision(1000);
double lo = - std::numeric_limits<double>::max() / 2 ;
double hi = + std::numeric_limits<double>::max() / 2 ;
boost::random::uniform_real_distribution<double> boost_distrib(lo, hi);
std::cout << "lo " << lo << '\n';
std::cout << "hi " << hi << "\n\n";
std::cout << "boost distrib gen " << boost_distrib(gen) << '\n';
}

最佳答案

顺便说一句,您可以编写 boost::mt19937 gen(4294653137UL); 以避免在默认构造函数中使用默认种子 (5489) 进行播种。您的代码必须遍历生成器内部状态的所有 624 个 uint32_t 元素两次。


生成器总是很好,并且在任何机器上都可以正常工作。区别仅在于使用 float 将其映射到 uniform_real_distribution

g++ -m32 -msse2 -mfpmath=sse 为所有其他编译器生成相同的输出。 32 位与 64 位不同,因为 64 位使用 SSE 进行浮点运算,所以 double 临时对象始终是 64 位。 32 位 x86 默认使用旧版 x87 FPU,其中所有内容在内部都是 80 位,并且在存储到内存时仅四舍五入为 64 位 double

Note that bit-identical FP results in genral is NOT guaranteed with different compilers even on the same platform.

默认情况下,32 位 clang 仍然使用 SSE 数学,因此它获得与 64 位 clang 或 64 位 g++ 相同的结果。告诉 g++ 做同样的事情解决了这个问题。 -mfpmath=sse 告诉它使用 SSE 进行计算(尽管它不会更改 ABI,因此浮点返回值仍在 x87 st(0) 中。) -msse2 告诉 g++ 假设目标机器支持 SSE 和 SSE2。 ( 的单精度添加了 double 。SSE2 是 x86-64 架构中的基线,用于在 64 位 ABI 中传递/返回 FP args。)

如果没有 SSE,您可以(但不要)使用-ffloat-store 来精确遵循 C 标准并舍入中间结果通过存储和重新加载它们到 32 或 64 位。这为每个 FP 数学指令增加了大约 6 个周期的延迟。 (与 Intel Haswell 上的 3 周期 FP add 和 5 周期 FP mul 相比。)所以不要这样做,你会得到可怕的代码。


调试步骤:我在 Ubuntu 15.10 上使用 g++ 5.2、clang-3.5 和 clang-3.8(来自 http://llvm.org/apt/)进行了试用。

for i in ./boost-random-seedint*; do echo -ne "$i:\t" ; $i|md5sum ;done
./boost-random-seedint-g++32: 53d99523ca2afeac428eae2c89e69974 -
./boost-random-seedint-g++64: a59f08c0bc22b8753c474db077b809bd -
./boost-random-seedint-clang3.5-32: a59f08c0bc22b8753c474db077b809bd -
./boost-random-seedint-clang3.5-64: a59f08c0bc22b8753c474db077b809bd -
./boost-random-seedint-clang3.8-32: a59f08c0bc22b8753c474db077b809bd -
./boost-random-seedint-clang3.8-64: a59f08c0bc22b8753c474db077b809bd -

所以唯一的异常(exception)是 32 位 g++。所有其他输出具有相同的哈希值

编译器选项:

clang++-3.8 -m32 -O1 -g boost-random-seedint.cpp -o boost-random-seedint-clang3.8-32  # and similiar
g++ -m32 -Og -g boost-random-seedint.cpp -o boost-random-seedint32

clang 没有 -Og。带有 -O0 和 -O3 的 32 位 g++ 生成的二进制文件与 -Og 的输出相同。


调试 32 位和 64 位二进制文​​件:在默认种子之后和调用 gen.seed(4294653137UL) 之后,它们的状态数组是相同的。

关于c++ - boost::random::uniform_real_distribution 应该在处理器之间相同吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33789476/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com