/** * @file test.cpp * @brief xorshift乱数の速度テスト * @author tenk* * @date 2010-1 */ #define XORSHIFTRAND_TEST #include <stdio.h> #include <stdlib.h> #include "XorShiftRand.h" #include "MtRand.h" //static unsigned DSP(unsigned r) { printf("%#10x\n", r); return r; } #define DSP(x) x // =========================================================================== /// 適当な線形合同法の乱数. (http://www001.upp.so-net.ne.jp/isaku/rand.html の rand( )その1) class Test_Rand1 { unsigned s_; public: Test_Rand1() : s_(1) {} unsigned operator()() { //return (s_ = s_ * 1103515245+12345) & 2147483647; // どうせなら>>1のほうがいい. return (s_ = s_ * 1103515245+12345); // がこの例では最上位ビットをoffする必要なし. } }; /// C標準ライブラリの rand() を呼び出す. struct Test_Clib_Rand { unsigned operator()() { return rand(); } }; // =========================================================================== // 時間計測関係 #ifdef _WIN32 #include <windows.h> typedef unsigned __int64 PERFCNT_T; PERFCNT_T PERFCNT_get() { PERFCNT_T c; QueryPerformanceCounter((LARGE_INTEGER*)&c); return c; } PERFCNT_T PERFCNT_per_sec() { static PERFCNT_T s = 0; if (!s) QueryPerformanceFrequency((LARGE_INTEGER*)&s); return s; } #elif defined LINUX #include <sys/resource.h> typedef unsigned long long PERFCNT_T; PERFCNT_T PERFCNT_get() { struct rusage t; getrusage(RUSAGE_SELF, &t); return t.ru_utime.tv_sec * 1000000ULL + t.ru_utime.tv_usec; } #define PERFCNT_per_sec() 1000000ULL #else #include <time.h> typedef clock_t PERFCNT_T; #define PERFCNT_get() clock() #define PERFCNT_per_sec() CLOCKS_PER_SEC #endif // =========================================================================== // 計測&チェック unsigned g_dummy_var; template<class RND> double benchmark(RND rnd, size_t count, unsigned flags, const char* ttl) { PERFCNT_T start_tick; PERFCNT_T elapsed; unsigned j; double e; unsigned char verboss = flags & 1; if (verboss) { fprintf(stderr, "\t%s:start\n", ttl); } start_tick = PERFCNT_get(); // 計測開始 for (j = 0; j < count; ++j) { g_dummy_var = DSP( rnd() ); } elapsed = PERFCNT_get() - start_tick; // 計測終了 e = elapsed * 1.0 / ((double)PERFCNT_per_sec() * (double)count); if (verboss) { fprintf(stderr, "\t%s:end (%f)\n", ttl, e * 1000000.0); } return e; // 計測された時間. } static void test_all(unsigned count, unsigned flags) { enum { N = 64 }; const char* nm[N] = {0}; double elaped[N] = { 0 }; printf( "\nxor-shift乱数の実行計測(%9d回実行の平均) 単位:ナノ秒\n", count ); // いくつかのテスト呼び出し. { unsigned k = 0; nm[k] = "XorShift 32" ; elaped[k] = benchmark(XorShiftRand<32>() , count, flags, nm[k]); ++k; nm[k] = "XorShift 64" ; elaped[k] = benchmark(XorShiftRand<64>() , count, flags, nm[k]); ++k; nm[k] = "XorShift 96" ; elaped[k] = benchmark(XorShiftRand<96>() , count, flags, nm[k]); ++k; nm[k] = "XorShift 128" ; elaped[k] = benchmark(XorShiftRand<128>(), count, flags, nm[k]); ++k; nm[k] = "XorShift 160" ; elaped[k] = benchmark(XorShiftRand<160>(), count, flags, nm[k]); ++k; nm[k] = "XorShift 192" ; elaped[k] = benchmark(XorShiftRand<192>(), count, flags, nm[k]); ++k; nm[k] = "XorShift 256" ; elaped[k] = benchmark(XorShiftRand<256>(), count, flags, nm[k]); ++k; nm[k] = "LCG " ; elaped[k] = benchmark(Test_Rand1() , count, flags, nm[k]); ++k; nm[k] = "clib rand " ; elaped[k] = benchmark(Test_Clib_Rand() , count, flags, nm[k]); ++k; nm[k] = "MT Rand " ; elaped[k] = benchmark(MtRand() , count, flags, nm[k]); ++k; } for (unsigned j = 0; j < N; ++j) { double e; if (nm[j] == 0) continue; printf(",%-21s ,", nm[j]); e = elaped[j] * 1000000000.0; if (e > 0) printf("%12.3f,", e); else printf("%12s,", "---"); printf("\n"); } } // =========================================================================== /** 使い方. */ static int usage() { fprintf(stderr, "usage>test [-opts] file(s)\n" " xor shift 乱数の 速度チェック.\n" " -cN 試行回数の指定\n" " -v 経過メッセージを増やす\n" ); return 1; } /** メイン. */ int main(int argc, const char* argv[]) { int i; unsigned count = 1; unsigned flags = 0; if (argc < 2) return usage(); // オプション取得. for (i = 1; i < argc; ++i) { const char* a = argv[i]; if (a[0] == '-') { if (a[1] == 'v') { flags = 1; // verboss; } else if (a[1] == 'c') { count = strtol(a+2,0,0); if (count < 1) count = 1; } else { return usage(); } } } test_all(count, flags); return 0; }