【问题标题】:Enhancing program performance提高计划绩效
【发布时间】:2018-09-07 03:29:50
【问题描述】:

我仍然是一个尝试获得 c++ 基础知识的初学者。我一直在编写一个控制台应用程序,它可以打印出特定范围内的素数,这里是代码(我正在使用 CodeBlocks ):

bool isInteger(double i)
{
    int x = i;
    if ( i/x == 1)
    {
        return true;
    }else
    {
        return false;
    }
}

int DivTimes(double i)
{
    int counter = 0;
    for (int y = 2; y <= i; y++)
    {
        if (isInteger(i/y))
        {
            counter ++;
        }
    }
    return counter;
}

bool isPrime(double i)
{
    if (DivTimes(i) > 1)
        return false;
    else
        return true;
}

int main()
{
    for(int i = 999999910; i <= 1000000000 ; i++)
    {
        if (isPrime(i))
            cout << " " << i;
    }
}

对于像 1E9 这样的大量数字,我的程序的性能变得非常缓慢,并且只使用了我 10% 的 CPU。所以,我想知道有什么方法可以让我的程序利用更多的 CPU 能力并提高程序性能?

【问题讨论】:

  • 您可能想对素性的有效测试进行一些研究。
  • 如果您仔细查看这 10%,您是否获得了计算机所有内核的 10% 和一个内核的约 100%?
  • 半相关:为了获得最佳性能结果,请确保您在构建代码时启用并启用了优化。不太熟悉 Code::Blocks,但这可能就像告诉 Code::Blocks 生成“发布”版本一样简单。
  • 用双打扔掉所有的东西。这些是完全不必要的,并且由于浮点错误而不能一直工作。要检查一个数字是否可以被另一个数字整除,只需检查a % b == 0。查找在一定范围内生成素数的方法,因为有比您使用的算法更有效的算法。

标签: c++ performance cpu-usage


【解决方案1】:

这个速度应该很容易提高很多。

第一步基于简单的数学运算:一个数的因数成对匹配:如果一对中的一个因数大于该数的平方根,则另一个小于该数的平方根。

这意味着我们只需要查看直到(包括)数字平方根的因素。如果没有小于或等于平方根的因数,也不会有任何大于平方根的因数。我们也可以在找到一个因子(不是 1)后立即停止查找,因为这足以告诉我们这个数字不是素数。最后,我们可以从尝试除以 2 开始。如果数字除以 2,则它不是素数,我们就完成了。否则,我们知道它是奇数,我们不需要尝试除以任何其他偶数。因此,在检查可被 2 整除后,我们从 3 开始循环,每次都加 2 而不是加 1。

让我们考虑一下 1e9 的速度差异。现在,您正在执行大约 1e9 个分区。 1e9 的平方根约为 31,623。我们只需要尝试除以奇数,所以我们将其减半,所以最坏的情况是我们尝试除以 15,811 个不同的数字。因此,以整数计算,我们将工作速度提高了大约 1e9/15811 = 63,000。

如果您想走得更远,可以查看埃拉托色尼筛。使用它,您可以在大约 30 秒内找到所有 50847534 个最高 1e9 的素数(在我的机器上大约需要 29 秒,使用旧的 AMD A8-7600,它不仅有 5 年的历史,而且是一个相当慢的 CPU,即使它是新的)。

在那之后你可以做更多的事情(分段筛、阿特金斯筛等),但这至少足以让你开始。

就 CPU 使用率而言:其中大多数是单线程的,因此希望它们 100% 使用一个内核,但仅此而已。多线程素数搜索可能有点不重要。我会先集中精力有效地使用一个核心。

哦——我差点忘了。对于它的价值(很少),这是最简单的 Eratosthenes 筛子版本的一些代码。它应该比你的速度快很多,但仍有很大的改进空间。

#include <vector>
#include <iostream>

unsigned long primes = 0;

int main() {
    int number = 1'000'000'000;
    std::vector<bool> sieve(number,false);
    sieve[0] = sieve[1] = true;

    for(int i = 2; i<number; i++) {
        if(!sieve[i]) {
            ++primes;
            for (int temp = 2*i; temp<number; temp += i)
                sieve[temp] = true;
        }
    }
    std::cout << "found: " << primes << " Primes\n";
    return 0;
}

【讨论】:

    【解决方案2】:

    简答:不要。

    长答案: 这可能最适合在计算机科学 SE 中提出,因为它不是关于 C++,而是关于算法。

    您可以考虑很多事情,例如集成多线程动态编程方法并将它们合并。即便如此,您最终可能会得到可能需要数年才能运行的代码。

    如果您有正当理由使用天文数字,那么没有 C++ 编译器可以帮助您,您最好使用专门的数学平台。我们在我去的大学使用Magma

    您可能找不到任何人直接为您提供代码,因为您要完成的工作并不容易。祝你好运。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-14
      • 2014-02-24
      • 1970-01-01
      • 2013-04-24
      • 1970-01-01
      相关资源
      最近更新 更多