c++ 我可以通过先使用内存来加快我的文本文件写入速度吗?

hsgswve4  于 2023-05-30  发布在  其他
关注(0)|答案(1)|浏览(109)

下面是我的C++代码,我正在努力加快速度。我如何写入内存,然后在最后将整个文件转储到“Primes List.txt”?如果你能帮上忙的话,谢谢你。

#include <vector>
#include <iostream>
#include <fstream>
#include <chrono>
using namespace std;

int main()
{
    cout << "\n\n\n     Calculating all Prime Numbers up to 82,000,000";
    cout << "\n\n     You will have to give me exactly a minute! ...";
    cout << "\n\n     ";
    auto start = chrono::steady_clock::now();
    ofstream myfile;
    myfile.open("Primes List.txt");
    myfile << "2\n";
    vector<int> primes;
    primes.push_back(2);
    for (int i = 3; i < 82000000; i++)
    {
        bool prime = true;
        for (int j = 0; j < primes.size() && primes[j] * primes[j] <= i; j++)
        {
            if (i % primes[j] == 0)
            {
                prime = false;
                break;
            }
        }
        if (prime)
        {
            primes.push_back(i);
            myfile << i << "\n";
         }
     }
    auto end = chrono::steady_clock::now();
    chrono::duration<double> elapsed_seconds = end - start;
    myfile << "\n Elapsed Time: " << elapsed_seconds.count() << " seconds\n";
    cout << "Elapsed Time: " << elapsed_seconds.count() << " seconds\n\n\n";
    myfile.close();
    system("pause");
return 0;
}

我在一台相当强大的PC上运行这个程序,希望它运行得更快。

qojgxg4l

qojgxg4l1#

正如多位评论者所指出的,第一个问题是加快总理一代。下面的代码1)使用了一个位图作为筛选,这大大减少了所需的内存,2)只检查+/-1 mod 6的数字。
这是我所知道的最快的筛法。在我的机器上,它只花了108ms就可以覆盖高达82M。筛选的几率是180ms,我没有足够的耐心来衡量规范的筛选算法。

示例代码

auto sieve_mod6_prime_seq(int max = int{1} << 20) {
    std::vector<int> primes;
    primes.push_back(2);
    primes.push_back(3);

    auto max_index = max / 3;
    auto bits_per = sizeof(uint64_t) * CHAR_BIT;
    auto nwords = (bits_per + max_index - 1) / bits_per;
    std::vector<uint64_t> words(nwords);

    words[0] |= 1;
    size_t wdx = 0;
    while (wdx < nwords) {
        auto b = std::countr_one(words[wdx]);
        auto p = 3 * (64 * wdx + b) + 1 + (b bitand 1);
        if (b < 64 and p < max) {
            primes.push_back(p);

            for (auto j = p; j < max; j += 6 * p) {
                auto idx = j / 3;
                auto jdx = idx / 64;
                auto jmask = uint64_t{1} << (idx % 64);
                words[jdx] |= jmask;
            }

            for (auto j = 5 * p; j < max; j += 6 * p) {
                auto idx = j / 3;
                auto jdx = idx / 64;
                auto jmask = uint64_t{1} << (idx % 64);
                words[jdx] |= jmask;
            }
        }
        else {
            ++wdx;
        }
    }
    return primes;
}

对于没有std::countr_one可用的C++版本,下面是一个实现。

// If we are using gcc or clang, using the compiler builtin.
#if defined(__GNUC__) || defined(__clang__)

int countr_one(unsigned int n) {
    return ~n == 0 ? (sizeof(unsigned int) * CHAR_BIT) : __builtin_ctz(~n);
}

int countr_one(unsigned long int n) {
    return ~n == 0 ? (sizeof(unsigned long int) * CHAR_BIT) : __builtin_ctzl(~n);
}

int countr_one(unsigned long long int n) {
    return ~n == 0 ? (sizeof(unsigned long long int) * CHAR_BIT) : __builtin_ctzll(~n);
}

// Otherwise, a standards compliant implementation
#else

int countr_one(uint32_t n) {
    n = ~n & (n+1);   // this gives a 1 to the left of the trailing 1's
    n--;              // this gets us just the trailing 1's that need counting
    n = (n & 0x55555555) + ((n>>1) & 0x55555555);  // 2 bit sums of 1 bit numbers
    n = (n & 0x33333333) + ((n>>2) & 0x33333333);  // 4 bit sums of 2 bit numbers
    n = (n & 0x0f0f0f0f) + ((n>>4) & 0x0f0f0f0f);  // 8 bit sums of 4 bit numbers
    n = (n & 0x00ff00ff) + ((n>>8) & 0x00ff00ff);  // 16 bit sums of 8 bit numbers
    n = (n & 0x0000ffff) + ((n>>16) & 0x0000ffff); // sum of 16 bit numbers
    return n;
}

int countr_one(uint64_t n) {
    n = ~n & (n+1);
    n--;
    n = (n & 0x5555555555555555ul) + ((n>>1) & 0x5555555555555555ul);
    n = (n & 0x3333333333333333ul) + ((n>>2) & 0x3333333333333333ul);
    n = (n & 0x0f0f0f0f0f0f0f0ful) + ((n>>4) & 0x0f0f0f0f0f0f0f0ful);
    n = (n & 0x00ff00ff00ff00fful) + ((n>>8) & 0x00ff00ff00ff00fful);
    n = (n & 0x0000ffff0000fffful) + ((n>>16) & 0x0000ffff0000fffful);
    n = (n & 0x00000000fffffffful) + ((n>>32) & 0x00000000fffffffful);
    return n;
}

#endif

相关问题