Last active
December 20, 2015 02:38
-
-
Save kaixiong/6057346 to your computer and use it in GitHub Desktop.
Benchmarks of various ways to generate random numbers in a given range
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdint> | |
#include <ctime> | |
#include <random> | |
#include <boost/format.hpp> | |
#define RUN_COUNT 100000 | |
#define RANGE_MIN 100 | |
#define RANGE_MAX 100000 | |
typedef std::minstd_rand PRNG; | |
namespace { | |
inline uint64_t timestamp () | |
{ | |
timespec time; | |
clock_gettime (CLOCK_MONOTONIC, &time); | |
return time.tv_sec * uint64_t (1000000000) + time.tv_nsec; | |
} | |
} | |
int main (int argc, char** argv) | |
{ | |
PRNG prng; | |
std::vector<uint32_t> array {RUN_COUNT}; | |
array.resize (RUN_COUNT); | |
// #1: Modulo | |
auto start_time = timestamp (); | |
for (unsigned int i = 0; i < RUN_COUNT; i++) { | |
array[i] = prng () % (RANGE_MAX - RANGE_MIN + 1) + RANGE_MIN; | |
} | |
auto time1 = timestamp () - start_time; | |
// #2: Scaling with integer multiplication and division | |
start_time = timestamp (); | |
for (unsigned int i = 0; i < RUN_COUNT; i++) { | |
array[i] = (prng () * (RANGE_MAX - RANGE_MIN)) / (prng.max () - prng.min ()) + RANGE_MIN; | |
} | |
auto time2 = timestamp () - start_time; | |
// #3: Scaling with floating-point multiplication and division | |
start_time = timestamp (); | |
for (unsigned int i = 0; i < RUN_COUNT; i++) { | |
array[i] = float (prng ()) / (prng.max () - prng.min ()) * (RANGE_MAX - RANGE_MIN) + RANGE_MIN; | |
} | |
auto time3 = timestamp () - start_time; | |
// #4: C++11's std::uniform_int_distribution | |
start_time = timestamp (); | |
for (unsigned int i = 0; i < RUN_COUNT; i++) { | |
std::uniform_int_distribution<uint32_t> distrib{RANGE_MIN, RANGE_MAX}; | |
array[i] = distrib (prng); | |
} | |
auto time4 = timestamp () - start_time; | |
// #5: C++11's std::uniform_int_distribution (reused) | |
start_time = timestamp (); | |
std::uniform_int_distribution<uint32_t> distrib{RANGE_MIN, RANGE_MAX}; | |
for (unsigned int i = 0; i < RUN_COUNT; i++) { | |
array[i] = distrib (prng); | |
} | |
auto time5 = timestamp () - start_time; | |
// Display timings for comparison | |
std::cout << boost::format {"Method 1: %.8f (%+.4f%%)\n"} % (double (time1) / 1000000000.0) % (double (time1) / time1 * 100.0 - 100.0); | |
std::cout << boost::format {"Method 2: %.8f (%+.4f%%)\n"} % (double (time2) / 1000000000.0) % (double (time2) / time1 * 100.0 - 100.0); | |
std::cout << boost::format {"Method 3: %.8f (%+.4f%%)\n"} % (double (time3) / 1000000000.0) % (double (time3) / time1 * 100.0 - 100.0); | |
std::cout << boost::format {"Method 4: %.8f (%+.4f%%)\n"} % (double (time4) / 1000000000.0) % (double (time4) / time1 * 100.0 - 100.0); | |
std::cout << boost::format {"Method 5: %.8f (%+.4f%%)\n"} % (double (time5) / 1000000000.0) % (double (time5) / time1 * 100.0 - 100.0); | |
return EXIT_SUCCESS; | |
} | |
/* | |
g++ -O2 -g -Wall -pedantic -std=c++11 random.cpp -o random -lr | |
Results: | |
kaixiong@kaixiong-zenbook:~/Documents/projects/expt$ ./random | |
Method 1: 0.00222034 (+0.0000%) | |
Method 2: 0.00218799 (-1.4567%) | |
Method 3: 0.00221519 (-0.2318%) | |
Method 4: 0.00922058 (+315.2783%) | |
Method 5: 0.00278417 (+25.3938%) | |
kaixiong@kaixiong-zenbook:~/Documents/projects/expt$ ./random | |
Method 1: 0.00226707 (+0.0000%) | |
Method 2: 0.00213056 (-6.0214%) | |
Method 3: 0.00223113 (-1.5853%) | |
Method 4: 0.00489745 (+116.0251%) | |
Method 5: 0.00284279 (+25.3945%) | |
kaixiong@kaixiong-zenbook:~/Documents/projects/expt$ ./random | |
Method 1: 0.00227261 (+0.0000%) | |
Method 2: 0.00214656 (-5.5465%) | |
Method 3: 0.00220350 (-3.0407%) | |
Method 4: 0.00698950 (+207.5542%) | |
Method 5: 0.00282391 (+24.2587%) | |
kaixiong@kaixiong-zenbook:~/Documents/projects/expt$ ./random | |
Method 1: 0.00227164 (+0.0000%) | |
Method 2: 0.00215942 (-4.9398%) | |
Method 3: 0.00214239 (-5.6896%) | |
Method 4: 0.00779363 (+243.0841%) | |
Method 5: 0.00276684 (+21.7992%) | |
kaixiong@kaixiong-zenbook:~/Documents/projects/expt$ ./random | |
Method 1: 0.00222016 (+0.0000%) | |
Method 2: 0.00217719 (-1.9351%) | |
Method 3: 0.00223086 (+0.4821%) | |
Method 4: 0.00912261 (+310.8992%) | |
Method 5: 0.00275899 (+24.2701%) | |
kaixiong@kaixiong-zenbook:~/Documents/projects/expt$ ./random | |
Method 1: 0.00221965 (+0.0000%) | |
Method 2: 0.00216394 (-2.5101%) | |
Method 3: 0.00220133 (-0.8252%) | |
Method 4: 0.00622905 (+180.6318%) | |
Method 5: 0.00283261 (+27.6150%) | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment