【问题标题】:Why is this C++ program slower than Node.js equivalent?为什么这个 C++ 程序比 Node.js 慢?
【发布时间】:2021-06-17 21:58:36
【问题描述】:

我正在学习 C++,并决定重新制作一个旧的 Node.js 程序,看看它会快多少,因为据我所知,C++ 应该会因为编译而快得多。

这个程序很简单,就是求素数。它使用与我的 Node.js 程序完全相同的逻辑,但需要 8 到 9 秒,而 Node.js 只需要 4 到 5 秒。

#include <iostream>
#include <string>
#include <ctime>

using namespace std;


// Declare functions
int main();
bool isPrime(int num);
bool is6n_1(int num);

// Define variables
int currentNum = 5;         // Start at 5 so we iterate over odd numbers, we add 2 and 3 manually
int primesToFind = 1000000;
int primesFound = 2;
int* primes = NULL;



// Main
int main() {

    // Create dynamic memory primes array
    primes = new int[1000000];
    primes[0] = 2;
    primes[1] = 3;

    cout << "Finding primes..." << endl;
    time_t start_time = time(NULL);


    // Main execution loop
    for (; primesFound < primesToFind; currentNum += 2) {
        if (isPrime(currentNum)) {
            primes[primesFound] = currentNum;
            primesFound++;
        }
    }

    time_t end_time = time(NULL);
    cout << "Finished" << endl;
    cout << end_time - start_time << endl;

    return 0;
}



// Check whether a number is prime
// Dependant on primes[]
bool isPrime(int num) {

    // We divide it by every previous prime number smaller than the sqrt
    // and check the remainder
    for (int i = 1; i <= sqrt(num) && i < primesFound; i++) {       // Start i at 1 to skip the first unnecessary modulo with 2
        if (num % primes[i] == 0) {                                 // because we increment by 2
            return false;
        }
    }
    return true;
}

因为我是 C++ 新手,我不知道这是由于代码效率低下(可能)还是因为编译器或 Visual Studio IDE 中的某些设置。

我正在使用 Visual Studio 2019 社区、发布版本和具有 O2 优化的 x64 架构。

如何让这个程序更快?

【问题讨论】:

  • for(int i = 1; i &lt;= sqrt(num) ...) i 是一个索引。你的意思是primes[i] &lt;= sqrt(num)? (实际上,可以进一步重写以处理一些边界检查并避免浮点计算,但这将是此代码运行速度比您预期慢的主要原因。)
  • 对于for循环的每次迭代,大部分计算可能都用于计算sqrt(num),将值存储在循环外的变量中
  • 代码有明显的拼写错误;检查i(索引)是否小于当前候选人的 sqrt 是没有意义的,你想要的是primes[i] &lt; sqrt(currentNum)。另请注意,检查 primes[i]*primes[i] &lt; currentNum 是否等效但更快。
  • @6502 您实际上应该检查&lt;=,否则您可能会认为49 是素数。
  • 你可能还想展示你的 NodeJS 代码。

标签: c++ visual-studio c++14


【解决方案1】:

关于编译器设置,我只能说:

  • 使用 x64,而不是 x86(32 位)作为目标
  • 使用 Release 作为配置,而不是 Debug
  • 启用积极优化

(编辑)您似乎已经在编译器中进行了这些设置,因此关于编译器应该没有什么明显的事情要做。

此外,可能还有很多优化可能,因为您似乎没有使用埃拉托色尼筛。然后,您可以进一步跳过所有 2 的倍数,并将步长增加到树。

您当然必须提供 node.js 代码。我几乎可以肯定它没有使用 exact 相同的逻辑。

【讨论】:

  • 根据提问者的说法,您关于编译器优化的所有建议都已经生效,并且提问者正在使用eratosthenes的筛子。我也不确定将步长从 2 增加到 3 是否能正常工作。在这种情况下,您将开始不必要地测试一堆偶数并跳过孪生素数。
  • @NathanPierson 在我看来,他们没有正确使用筛子。他们每次都检查素数,而不是在找到一个素数的所有倍数后将其划掉。仅仅因为它们将上限限制为目标数字的 sqrt,并不能使其正确。
  • 关于试除法和实际筛分区别的好点。
猜你喜欢
  • 2016-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-13
  • 1970-01-01
相关资源
最近更新 更多