Генерация случайных чисел может быть выполнена с помощью rand()
или std::mt19997
. Последний является предпочтительным, я все еще тестировал для обоих случаев. (Visual Studio 2017 Community x64). Я использую фиктивную переменную, чтобы компилятор не мог игнорировать случайные операторы генерации. rand()
возвращает int
, а std::mt19937
возвращает std::uint32_t
. Поэтому, чтобы уменьшить количество приведений, я использую 2 фиктивные переменные.
#include <iostream>
#include <random>
#include <chrono>
#include <limits>
#include <string>
#include <cstdlib>
namespace util {
constexpr std::size_t loop{ 10'000'000u };
std::mt19937 engine{ std::random_device{}() };
int rand_dummy{ 0 };
std::uint32_t mt19937_dummy{ 0u };
}
void rand_mod() {
for (std::size_t i = 0u; i < util::loop; ++i) {
util::rand_dummy = (rand() % 100);
}
}
void rand_div() {
for (std::size_t i = 0u; i < util::loop; ++i) {
util::rand_dummy = static_cast<int>(static_cast<double>(rand()) / RAND_MAX * 100);
}
}
void mt19937_mod() {
for (std::size_t i = 0u; i < util::loop; ++i) {
util::mt19937_dummy = (util::engine() % 100u);
}
}
void mt19937_div() {
for (std::size_t i = 0u; i < util::loop; ++i) {
util::mt19937_dummy = static_cast<std::uint32_t>(static_cast<double>(util::engine()) / std::numeric_limits<std::uint32_t>::max() * 100u);
}
}
void benchmark(void(*f)(void), const std::string& name) {
auto t1 = std::chrono::high_resolution_clock::now();
f();
auto t2 = std::chrono::high_resolution_clock::now();
std::cout << name << std::chrono::duration_cast<std::chrono::nanoseconds>(t2 - t1).count() / 1e6 << "ms\n";
}
int main() {
srand(std::random_device{}());
benchmark(rand_mod, "rand() | mod: ");
benchmark(rand_div, "rand() | div: ");
std::cout << "---------------------------\n";
benchmark(mt19937_mod, "std::mt19937 | mod: ");
benchmark(mt19937_div, "std::mt19937 | div: ");
return util::rand_dummy + util::mt19937_dummy;
}
оптимизации отключены (/ Od):
rand() | mod: 956.128ms
rand() | div: 796.235ms
---------------------------
std::mt19937 | mod: 437.885ms
std::mt19937 | div: 584.477ms
полная оптимизация (/ Ox):
rand() | mod: 276.092ms
rand() | div: 262.224ms
---------------------------
std::mt19937 | mod: 61.4312ms
std::mt19937 | div: 103.38ms
std::mt19937
в обоих случаях быстрее
для std::mt19937
модуль выигрывает у деления
для rand()
делений выигрывает над модулем
Так что это зависит от того, какой вы используете. Поскольку std::mt19937
превосходит rand()
, ответ должен быть следующим: модуль быстрее деления.
> почему rand()
считается вредным>
Обратите внимание, что вы также не должны делать:
engine() % 100;
Вместо этого используйте std::uniform_int_distribiution(0, 99)(engine);
[engine
является std::mt19937
]