为什么 mt19937 的 STD 实现有双倍的 sizeof 作为增强版本?
Why do STD implementations of mt19937 have double sizeof as boost version?
我有一个带有意外输出的简单 C++ 程序:
#include<random>
#include<iostream>
#include "boost/random/mersenne_twister.hpp"
#include "boost/random/uniform_int_distribution.hpp"
int main(){
std::cout << sizeof(std::mt19937) << std::endl;
std::cout << sizeof(std::mt19937_64) << std::endl;
std::cout << sizeof(boost::random::mt19937) << std::endl;
std::cout << sizeof(boost::random::mt19937_64) << std::endl;
}
5000
2504
2504
2504
我发现有趣的是,mt19937(32 位)的标准实现的 sizeof 大约是 boost 版本的 2 倍,而 64 位的完美匹配。
因为MT用的多space所以差别真的不小
同样奇怪的是,严格指定的算法的实现会有如此不同的 sizeof,我们不是在谈论 std::string 实现者可能会选择不同的 SSO 缓冲区大小...
我最好的猜测是 boost 要么有错误,要么它实现了一些略有不同的 mt19937 版本,但维基百科是这样说的,暗示 boost 可能是正确的:
Relatively large state buffer, of 2.5 KiB,
编辑:boost 和 std 版本似乎都satisfy requirement 第 1000 个生成的值是 4123659995,所以 boost 似乎没有错误。
这是标准定义:
mersenne_twister_engine<
uint_fast32_t, // element of the buffer
32,
624, // size of the buffer
397, 31,
0x9908b0df, 11,
0xffffffff, 7,
0x9d2c5680, 15,
0xefc60000, 18, 1812433253>
问题是 GNU 选择 std::uint_fast32_t
是 64 位系统上的 64 位类型(这是一个好的还是坏的选择是单独的讨论)。因此,如果缓冲区包含 32 位整数,缓冲区将是预期的两倍。
这是 Boost 定义:
mersenne_twister_engine<
uint32_t,
32,
624,
397, 31,
0x9908b0df, 11,
0xffffffff, 7,
0x9d2c5680, 15,
0xefc60000, 18, 1812433253>
除了使用在所有系统上始终相同的固定宽度元素外,两者完全相同。
您可以将 std::mersenne_twister_engine
直接与 std::uint_least32_t
元素一起使用来解决此问题。使用此别名优于固定别名,因为它需要在所有系统上都受支持。
我有一个带有意外输出的简单 C++ 程序:
#include<random>
#include<iostream>
#include "boost/random/mersenne_twister.hpp"
#include "boost/random/uniform_int_distribution.hpp"
int main(){
std::cout << sizeof(std::mt19937) << std::endl;
std::cout << sizeof(std::mt19937_64) << std::endl;
std::cout << sizeof(boost::random::mt19937) << std::endl;
std::cout << sizeof(boost::random::mt19937_64) << std::endl;
}
5000
2504
2504
2504
我发现有趣的是,mt19937(32 位)的标准实现的 sizeof 大约是 boost 版本的 2 倍,而 64 位的完美匹配。
因为MT用的多space所以差别真的不小
同样奇怪的是,严格指定的算法的实现会有如此不同的 sizeof,我们不是在谈论 std::string 实现者可能会选择不同的 SSO 缓冲区大小...
我最好的猜测是 boost 要么有错误,要么它实现了一些略有不同的 mt19937 版本,但维基百科是这样说的,暗示 boost 可能是正确的:
Relatively large state buffer, of 2.5 KiB,
编辑:boost 和 std 版本似乎都satisfy requirement 第 1000 个生成的值是 4123659995,所以 boost 似乎没有错误。
这是标准定义:
mersenne_twister_engine<
uint_fast32_t, // element of the buffer
32,
624, // size of the buffer
397, 31,
0x9908b0df, 11,
0xffffffff, 7,
0x9d2c5680, 15,
0xefc60000, 18, 1812433253>
问题是 GNU 选择 std::uint_fast32_t
是 64 位系统上的 64 位类型(这是一个好的还是坏的选择是单独的讨论)。因此,如果缓冲区包含 32 位整数,缓冲区将是预期的两倍。
这是 Boost 定义:
mersenne_twister_engine<
uint32_t,
32,
624,
397, 31,
0x9908b0df, 11,
0xffffffff, 7,
0x9d2c5680, 15,
0xefc60000, 18, 1812433253>
除了使用在所有系统上始终相同的固定宽度元素外,两者完全相同。
您可以将 std::mersenne_twister_engine
直接与 std::uint_least32_t
元素一起使用来解决此问题。使用此别名优于固定别名,因为它需要在所有系统上都受支持。