如何从 C 程序中获得 100% 的 CPU 使用率

新手上路,请多包涵

这是一个非常有趣的问题,所以让我来设置场景。我在国家计算机博物馆工作,我们刚刚设法让一台 1992 年的 Cray Y-MP EL 超级计算机运行起来,我们真的很想看看它的运行速度有多快!

我们决定最好的方法是编写一个简单的 C 程序来计算素数并显示计算所需的时间,然后在快速的现代台式 PC 上运行该程序并比较结果。

我们很快想出了这个代码来计算素数:

 #include <stdio.h>
#include <time.h>

void main() {
    clock_t start, end;
    double runTime;
    start = clock();
    int i, num = 1, primes = 0;

    while (num <= 1000) {
        i = 2;
        while (i <= num) {
            if(num % i == 0)
                break;
            i++;
        }
        if (i == num)
            primes++;

        system("clear");
        printf("%d prime numbers calculated\n",primes);
        num++;
    }

    end = clock();
    runTime = (end - start) / (double) CLOCKS_PER_SEC;
    printf("This machine calculated all %d prime numbers under 1000 in %g seconds\n", primes, runTime);
}

在我们运行 Ubuntu(The Cray 运行 UNICOS)的双核笔记本电脑上,它运行良好,获得 100% 的 CPU 使用率,大约需要 10 分钟左右。当我回到家时,我决定在我的六核现代游戏 PC 上尝试一下,这就是我们遇到的第一个问题。

我首先将代码修改为在 Windows 上运行,因为那是游戏 PC 使用的,但很遗憾地发现该进程只获得了大约 15% 的 CPU 功率。我想这一定是 Windows 就是 Windows,所以我启动到 Ubuntu 的 Live CD,认为 Ubuntu 将允许该进程充分发挥其潜力,就像它之前在我的笔记本电脑上所做的那样。

但是我只有 5% 的使用率!所以我的问题是,我怎样才能使程序在我的游戏机上以 100% 的 CPU 利用率在 Windows 7 或 Live Linux 上运行?另一件很棒但不是必需的事情是,最终产品是否可以是一个可以在 Windows 机器上轻松分发和运行的 .exe。

非常感谢!

PS 当然,这个程序并不能真正与 Crays 8 专业处理器一起使用,那完全是另外一回事了……如果你知道关于优化代码以在 90 年代 Cray 超级计算机上工作的任何信息,也请给我们留言!

原文由 bag-man 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 857
2 个回答

如果你想要 100% CPU,你需要使用超过 1 个核心。为此,您需要多个线程。

这是使用 OpenMP 的并行版本:

我不得不将限制增加到 1000000 以使其在我的机器上花费超过 1 秒。

 #include <stdio.h>
#include <time.h>
#include <omp.h>

int main() {
    double start, end;
    double runTime;
    start = omp_get_wtime();
    int num = 1,primes = 0;

    int limit = 1000000;

#pragma omp parallel for schedule(dynamic) reduction(+ : primes)
    for (num = 1; num <= limit; num++) {
        int i = 2;
        while(i <= num) {
            if(num % i == 0)
                break;
            i++;
        }
        if(i == num)
            primes++;
//      printf("%d prime numbers calculated\n",primes);
    }

    end = omp_get_wtime();
    runTime = end - start;
    printf("This machine calculated all %d prime numbers under %d in %g seconds\n",primes,limit,runTime);

    return 0;
}

输出:

这台机器在 29.753 秒内计算了 1000000 以下的所有 78498 个素数

这是你的 100% CPU:

在此处输入图像描述

原文由 Mysticial 发布,翻译遵循 CC BY-SA 3.0 许可协议

您在多核机器上运行一个进程 - 所以它只在一个核心上运行。

解决方案很简单,因为您只是想固定处理器 - 如果您有 N 个内核,请运行您的程序 N 次(当然是并行)。

例子

这是一些并行运行您的程序 NUM_OF_CORES 的代码。这是 POSIXy 代码 - 它使用 fork - 所以你应该在 Linux 下运行它。如果我正在阅读的有关 Cray 的内容是正确的,那么移植此代码可能比其他答案中的 OpenMP 代码更容易。

 #include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

#define NUM_OF_CORES 8
#define MAX_PRIME 100000

void do_primes()
{
    unsigned long i, num, primes = 0;
    for (num = 1; num <= MAX_PRIME; ++num) {
        for (i = 2; (i <= num) && (num % i != 0); ++i);
        if (i == num)
            ++primes;
    }
    printf("Calculated %d primes.\n", primes);
}

int main(int argc, char ** argv)
{
    time_t start, end;
    time_t run_time;
    unsigned long i;
    pid_t pids[NUM_OF_CORES];

    /* start of test */
    start = time(NULL);
    for (i = 0; i < NUM_OF_CORES; ++i) {
        if (!(pids[i] = fork())) {
            do_primes();
            exit(0);
        }
        if (pids[i] < 0) {
            perror("Fork");
            exit(1);
        }
    }
    for (i = 0; i < NUM_OF_CORES; ++i) {
        waitpid(pids[i], NULL, 0);
    }
    end = time(NULL);
    run_time = (end - start);
    printf("This machine calculated all prime numbers under %d %d times "
           "in %d seconds\n", MAX_PRIME, NUM_OF_CORES, run_time);
    return 0;
}

输出

$ ./primes
Calculated 9592 primes.
Calculated 9592 primes.
Calculated 9592 primes.
Calculated 9592 primes.
Calculated 9592 primes.
Calculated 9592 primes.
Calculated 9592 primes.
Calculated 9592 primes.
This machine calculated all prime numbers under 100000 8 times in 8 seconds

原文由 cha0site 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题