Tôi đã viết một (-ish) thử nghiệm đơn giản cho cách tiếp cận tôi đã đề cập trong các ý kiến của OP. Nó rõ ràng không phải là thử nghiệm chiến đấu, nhưng ý tưởng được thể hiện - bạn sẽ có thể lấy nó từ đây.
Vì số lượng byte đọc nhỏ hơn rất nhiều so với nếu một byte sắp xếp toàn bộ động cơ, hiệu suất của hai phương pháp này thực sự có thể so sánh được. Thử nghiệm giả thuyết này, cũng như tối ưu hóa thêm, được để lại như một bài tập cho người đọc.
#include <iostream>
#include <random>
#include <chrono>
#include <cstdint>
#include <fstream>
using namespace std;
struct rng_wrap
{
// it would also be advisable to somehow
// store what kind of RNG this is,
// so we don't deserialize an mt19937
// as a linear congruential or something,
// but this example only covers mt19937
uint64_t seed;
uint64_t invoke_count;
mt19937 rng;
typedef mt19937::result_type result_type;
rng_wrap(uint64_t _seed) :
seed(_seed),
invoke_count(0),
rng(_seed)
{}
rng_wrap(istream& in) {
in.read(reinterpret_cast<char*>(&seed), sizeof(seed));
in.read(reinterpret_cast<char*>(&invoke_count), sizeof(invoke_count));
rng = mt19937(seed);
rng.discard(invoke_count);
}
void discard(unsigned long long z) {
rng.discard(z);
invoke_count += z;
}
result_type operator()() {
++invoke_count;
return rng();
}
static constexpr result_type min() {
return mt19937::min();
}
static constexpr result_type max() {
return mt19937::max();
}
};
ostream& operator<<(ostream& out, rng_wrap& wrap)
{
out.write(reinterpret_cast<char*>(&(wrap.seed)), sizeof(wrap.seed));
out.write(reinterpret_cast<char*>(&(wrap.invoke_count)), sizeof(wrap.invoke_count));
return out;
}
istream& operator>>(istream& in, rng_wrap& wrap)
{
wrap = rng_wrap(in);
return in;
}
void test(rng_wrap& rngw, int count, bool quiet=false)
{
uniform_int_distribution<int> integers(0, 9);
uniform_real_distribution<double> doubles(0, 1);
normal_distribution<double> stdnorm(0, 1);
if (quiet) {
for (int i = 0; i < count; ++i)
integers(rngw);
for (int i = 0; i < count; ++i)
doubles(rngw);
for (int i = 0; i < count; ++i)
stdnorm(rngw);
} else {
cout << "Integers:\n";
for (int i = 0; i < count; ++i)
cout << integers(rngw) << " ";
cout << "\n\nDoubles:\n";
for (int i = 0; i < count; ++i)
cout << doubles(rngw) << " ";
cout << "\n\nNormal variates:\n";
for (int i = 0; i < count; ++i)
cout << stdnorm(rngw) << " ";
cout << "\n\n\n";
}
}
int main(int argc, char** argv)
{
rng_wrap rngw(123456790ull);
test(rngw, 10, true); // this is just so we don't start with a "fresh" rng
uint64_t seed1 = rngw.seed;
uint64_t invoke_count1 = rngw.invoke_count;
ofstream outfile("rng", ios::binary);
outfile << rngw;
outfile.close();
cout << "Test 1:\n";
test(rngw, 10); // test 1
ifstream infile("rng", ios::binary);
infile >> rngw;
infile.close();
cout << "Test 2:\n";
test(rngw, 10); // test 2 - should be identical to 1
return 0;
}
Nguồn
2014-06-21 18:10:57
Bạn có thể tìm thấy [câu hỏi này] (http://stackoverflow.com/questions/11563963/writing-a-binary-file-in-c-very-fast) hữu ích. Khác hơn thế, tôi không nghĩ rằng nó có thể serialize một RNG (hoặc bất kỳ đối tượng, thực sự) mà không có một số kiến thức về việc thực hiện cơ bản. Nếu nó có thể xảy ra, nó có lẽ sẽ liên quan đến một số ... hackery kinky. –
@MoreAxes Câu hỏi được đề cập không liên quan. Ngoài ra, đây không phải là vấn đề về hiệu suất, mà là vấn đề tương thích giao diện: giao diện I/O không xuất phát từ bất kỳ lớp iostream nào và tôi không thể sử dụng các phương thức đã cung cấp mà không sao chép trước đó vào chuỗi, sau đó chuyển đổi thành nhị phân và cuối cùng viết nó bằng chức năng ChunkIO :: Writer :: dataWrite. – user877329
'g ++' 's và Ideone 'sizeof std :: mt19937' trả về giá trị tương ứng 8 và 4 byte lớn hơn những gì cần thiết để lưu trữ mảng trạng thái của Mersenne Twister.Nếu đây là một giá trị duy nhất trong cả hai trường hợp, thì tôi đặt cược đó là một con trỏ (tôi giả sử bạn đang sử dụng hệ thống 64 bit và Ideone), mà bạn cần phải xử lý phù hợp trong quá trình tuần tự hóa. Nếu nó là một giá trị không phải con trỏ (hoặc hai trong số chúng trong trường hợp 'g ++'), thì có thể an toàn để tuần tự hóa nó như là. –