什么更快?对整数进行取模,或将整数除以MAX_INT以获得浮点数,然后乘以所需的模数值并转换回整数?

时间:2019-06-05 08:37:06

标签: c++ performance

什么更快?

random() % 100;

static_cast<int>((random() / 4294967296) * 100);

我真的不知道如何正确地进行基准测试,并且在我的计算机上更快出现的结果在其他计算机上可能无法正常工作,因此我就谦虚地向Stackoverflow上的智者提出这个问题

1 个答案:

答案 0 :(得分:4)

可以使用rand()std::mt19997完成随机数的生成。后者是首选,我仍将这两种情况作为基准。 (Visual Studio 2017社区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(),因此答案应该是:模数比除法快。

> why rand() is considered harmful >


请注意,您也不应该这样做:

engine() % 100;

使用std::uniform_int_distribiution(0, 99)(engine);

[{enginestd::mt19937]