81

これは非常に興味深い質問なので、状況を説明しましょう。私は国立コンピューティング博物館で働いており、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 を実行) では、これは完全に機能し、CPU 使用率が 100% になり、約 10 分ほどかかりました。家に帰って、ヘキサコアの最新のゲーミング PC で試してみることにしました。ここで最初の問題が発生します。

ゲーム用 PC が Windows を使用していたため、最初にコードを Windows で実行するように調整しましたが、プロセスが CPU の能力の約 15% しか得られていないことがわかり、残念でした。WindowsはWindowsであるに違いないと考えたので、UbuntuのLive CDを起動して、以前のラップトップで行ったように、Ubuntuがプロセスを最大限に実行できると考えました。

ただし、使用率は 5% しかありません。私の質問は、Windows 7 またはライブ Linux のいずれかで 100% の CPU 使用率でゲーム マシン上でプログラムを実行するにはどうすればよいでしょうか? もう 1 つの素晴らしいことですが、必須ではありません。最終製品が 1 つの .exe であり、Windows マシンで簡単に配布して実行できる場合です。

どうもありがとう!

PS もちろん、このプログラムは Crays 8 専用プロセッサでは実際には動作しませんでした。それはまったく別の問題です... 90 年代の Cray スーパー コンピューターで動作するようにコードを最適化する方法について何かご存知でしたら、ぜひお知らせください。

4

9 に答える 9

82

100%CPUが必要な場合は、複数のコアを使用する必要があります。そのためには、複数のスレッドが必要です。

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は次のとおりです。

ここに画像の説明を入力してください

于 2012-02-11T22:27:09.327 に答える
24

マルチコア マシンで 1 つのプロセスを実行しているため、1 つのコアでのみ実行されます。

プロセッサをペグしようとしているだけなので、解決策は簡単です.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
于 2012-02-11T22:16:41.823 に答える
7

私たちは本当にそれがどれくらい速くなるかを見たいです!

素数を生成するアルゴリズムは非常に非効率的です。Pentium II-350 でわずか 8 秒で 50847534 素数を 1000000000 まで生成するprimegenと比較してください。

すべての CPU を簡単に消費するには、マンデルブロ集合を計算したり、複数のスレッド (プロセス) でモナリザを描画するために遺伝的プログラミングを使用したりするなど、非常に並列的な問題を解決できます。

もう 1 つのアプローチは、Cray スーパーコンピューターの既存のベンチマーク プログラムを使用して、最新の PC に移植することです。

于 2012-02-11T23:06:06.803 に答える
5

ヘキサコアプロセッサで15%を取得している理由は、コードが100%で1コアを使用しているためです。100/6 = 16.67%。これは、プロセススケジューリングで移動平均を使用すると(プロセスは通常の優先度で実行されます)、15%として簡単に報告できます。

したがって、100%CPUを使用するには、CPUのすべてのコアを使用する必要があります。16コアCPU用に6つの並列実行コードパスを起動し、Crayマシンのプロセッサ数に応じてこのスケールを設定します:)

于 2012-02-11T22:25:02.830 に答える
0

1つのコアをすばやく改善するには、システムコールを削除して、コンテキスト切り替えを減らします。次の行を削除します。

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

最初のものは、反復ごとに新しいプロセスを生成するため、特に悪いです。

于 2012-02-15T23:09:03.527 に答える
0

OpenMP などを使用して、プログラムを並列化してみてください。並列プログラムを構成するための非常にシンプルで効果的なフレームワークです。

于 2012-02-11T22:20:41.607 に答える