You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何我的C++实现的Atkin筛法质数搜索代码运行如此缓慢?

C++实现Atkin筛法性能异常排查问题

我对比了PHP/Lua/Python与C实现的Atkin筛法质数搜索算法性能,以C为基准,算法参考自Atkin筛法示例。四种语言都成功实现算法,并添加了输入搜索上限的交互循环(输入exit退出),测试结果如下:

测试结果

上限为1e6(共78498个质数)

  • Lua : ~0.18秒
  • PHP : ~0.8秒
  • Python3 : ~19秒

上限为1e5(共9592个质数)

  • C++ : ~12-13秒

C在上限低10倍的情况下性能远逊于Lua,这完全不符合预期——毕竟C本应比Lua快得多。我尝试过开启编译优化、用MS Visual Studio 2022(MSVC++20 ISO)编译、在笔记本和台式机(Ubuntu系统)上运行,甚至让亲友在他的机器上测试,结果始终一致:耗时约12-17秒(依机器而异)。

我究竟哪里做错了?

编译器选项与设备配置

  • MinGW64/Win10及GNU GCC/Ubuntu:
    g++ -std=c++20 -march=x86-64 -mtune=ivybridge -O3 primenum.cpp -o primenum.exe
    
  • MSVC20/Win10:Release模式,x64,ISO C20标准
  • 台式机:Win10x64/Ubuntu server 24.04 LTS,Intel i5-3570K Ivy Bridge
  • 笔记本:Win10x64,Intel i7-3537U Ivy Bridge

完整C++代码

#include <cmath>
#include <iostream>
#include <string>
using namespace std;
//=============================================================================
/* This C++ program generates all prime numbers (primes) up to
 * integer limit entered by user. Primes searching method implements Sieve
 * of Atkin algorithm.*/
//=============================================================================
// Convert string chars to lowercase
void str_tolower(string &str) {
    int length = str.length();
    for (int i = 0; i < length; ++i) {
        str[i] = (char)tolower(str[i]);
    }
}
// Sieve of Atkin algorithm main function
// ======================================
void SieveOfAtkin(size_t limit) {
    /* Initialise the sieve array with false values.
     * "2" and "3" are known to be prime.*/
    size_t length = limit + 1;
    size_t *sieve = new size_t[length]{};
    sieve[2] = 1;
    sieve[3] = 1;

    /* Mark sieve[n] is true if one of the following is true:
     * a) n = (4*x*x)+(y*y) has odd number of solutions, i.e., there exist
     * odd number of distinct pairs (x, y) that satisfy the equation and
     * n % 12 = 1 or n % 12 = 5.
     * b) n = (3*x*x)+(y*y) has odd number of solutions and n % 12 = 7
     * c) n = (3*x*x)-(y*y) has odd number of solutions, x > y and
     * n % 12 = 11.*/
    size_t n{}, x{}, y{};
    for (x = 0; x*x <= limit; ++x) {
        for (y = 0; y*y <= limit; ++y) {
            // (a)
            n = 4*x*x + y*y;
            if ((n <= limit) && (n % 12 == 1 || n % 12 == 5)) {
                sieve[n] = !sieve[n];
            }
            // (b)
            n = 3*x*x + y*y;
            if ((n <= limit) && (n % 12 == 7)) {
                sieve[n] = !sieve[n];
            }
            // (c)
            n = 3*x*x - y*y;
            if ((x > y) && (n <= limit) && (n % 12 == 11)) {
                sieve[n] = !sieve[n];
            }
        }
    }

    // Mark all multiples of squares as non-prime
    size_t r{}, i{};
    for (r = 5; r*r <= limit; ++r) {
        if (sieve[r]) {
            for (i = r*r; i <= limit; i += r*r) {
                sieve[i] = 0;
            }
        }
    }

    // Disable listing if 'limit' > 1086 (print only first 180 primes)
    bool disable_list_output = limit >= 1087 ? true : false;

    // Print primes using sieve[]
    size_t count{0};
    const unsigned char columns{20};

    for (size_t a = 2; a <= limit; ++a) {
        if (sieve[a]) {
            ++count;
            if (!disable_list_output) {
                cout.setf(ios::dec);
                cout.width(10);
                cout << a;
                if (count > 0 && count % columns == 0)
                    cout << endl;
            }
        }
    }

    delete[] sieve;
    if (disable_list_output) {
        cout << endl << "===========================================";
        cout << endl << "Primes count is over 180, listing disabled.";
    }

    cout << endl << "-------------------------------------------" << endl;
    cout << "Primes found: " << count << endl;
}

// Main loop of the program
// ========================
int main(void) {
    time_t start_time{};
    size_t limit{};
    string input{};
    float f_limit{};

    while (true) {
        // Read user input string
        cout << endl << "Enter positive integer, N > 3 : ";
        getline(cin, input);
        str_tolower(input);

        // Processing user input string
        // ----------------------------
        if (!cin or input.empty()) { // if input failed --> repeat 'while' loop
            continue;
        } else if (input == "exit") {
            // Successful program termination
            exit(EXIT_SUCCESS);
        } else {
            try { // if input is float --> OK...
                f_limit = stof(input);
            } catch (...) { // ...else --> repeat 'while' loop
                continue;
            }
            f_limit = stof(input);

            // Check if input is integer
            if (floor(f_limit) == f_limit) {
                limit = static_cast<size_t>(f_limit);
                start_time = time(NULL);
                SieveOfAtkin(limit);
                cout << "Execution time : " << time(NULL) - start_time << endl;
                cout << "===========================================" << endl;
            }
        }
    }
    return 0;
}

内容的提问来源于stack exchange,提问作者Dart Paul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 15:34:53