質問

現在行っているプロジェクトの1つでは、さまざまな同時使用可能プログラミング言語。

現時点では、スタックレスpython C ++ PThreads なので、これら2つの言語に焦点を当てていますが、他の言語はおそらく後でテストされるでしょう。もちろん、比較は可能な限り代表的で正確でなければならないため、最初に考えたのは、標準的な 同時/マルチスレッドベンチマークの問題 を探し始めることでした。適切なまたは標準のテスト/問題/ベンチマークを見つけます。

だから私の質問は次のとおりです:プログラミング言語のパフォーマンスをテストするための良い、簡単または迅速な問題についての提案はありますか(そしてプロセスの長所と短所を明らかにするために) )?

役に立ちましたか?

解決

ベンチマークゲームがクアッドコアマシンに移行した2008年9月以来、さまざまなプログラミング言語の多くのプログラムがクアッドコアを活用するように書き直されました-たとえば、最初の10個のマンデルブロプログラム

他のヒント

同時実行のパフォーマンスを確認するために、言語ではなくハードウェアとコンパイラをテストする必要がありますか?

並行性の観点からどれだけ簡単で生産的であるか、そしてロックミスをプログラマーがどれだけ「絶縁」するかという観点から、私は言語を見ているでしょう。

編集:並列アルゴリズムを設計する研究者としての過去の経験から、ほとんどの場合、並列パフォーマンスは、アルゴリズムの並列化方法と、基盤となるハードウェアのターゲット方法に大きく依存することがわかると思います。

また、ベンチマークは等しくないことで有名です。これは、並列環境ではさらに顕著です。たとえば、非常に大きな行列を「クランチ」するベンチマークはベクトルパイプラインプロセッサに適していますが、並列ソートはより汎用的なマルチコアCPUに適しています。

これらは役に立つかもしれません:

並列ベンチマーク

NAS並列ベンチマーク

まあ、いくつかの古典がありますが、異なるテストは異なる機能を強調します。一部の分散システムは、より堅牢で、メッセージの受け渡しがより効率的である場合があります。より多くのマシンにスケールアップする通常の方法は、多数の小さなメッセージを送信することであるため、メッセージのオーバーヘッドが大きいと、スケーラビリティが損なわれる可能性がありますあなたが試すことができるいくつかの古典的な問題は、エラトステネスの分散Sieveまたは実装が不十分なフィボナッチ数列計算機です(つまり、シリーズの8番目の数、7番目のマシンのスピン、6番目のマシンのスピン)。ほぼすべての分割統治アルゴリズムを同時に実行できます。 Conwayのゲームオブライフまたは熱伝達を同時に実装することもできます。これらのアルゴリズムはすべて異なる焦点を持っているため、1つの分散システムがそれらのすべてで最善を尽くすことはおそらくないことに注意してください。

すぐに実装するのが最も簡単な方法は、実装が不十分なフィボナッチ電卓ですが、スレッドの作成に重点を置き、スレッド間の通信をあまり重視しません。

  

ハードウェアをテストする必要があります   および言語ではなくコンパイラ   同時実行性のパフォーマンスについて

いいえ、ハードウェアとコンパイラは私のテストの目的には関係ありません。ある言語で書かれたコードが別の言語のコードとどれだけうまく競合できるかをテストできるいくつかの良い問題を探しています。並行プログラミングを行うために、特定の言語で使用可能な構成体を実際にテストしています。そして、基準の1つはパフォーマンス(時間内に測定)です。

私が探している他のテスト基準のいくつかは次のとおりです。

  • 正しいコードを書くのは簡単です。なぜなら、同時プログラミングはシングルスレッドプログラムを書くよりも難しいからです
  • 同時プログラミングに使用される技術は何ですか:イベント駆動型、アクターベース、メッセージ解析、...
  • プログラマー自身が記述する必要があるコードの量と、プログラマーが自動的に行うコードの量:これは、所定のベンチマークの問題でテストすることもできます
  • 抽象化のレベルは何ですか?また、マシンコードに変換されたときにどのくらいのオーバーヘッドが含まれますか

したがって、実際には、パフォーマンスを the のみで最高のパラメーター(実際には言語自体ではなくハードウェアとコンパイラーに送信する)を探しているわけではありません。プログラマーの観点から、どの言語がどのような問題に最も適しているか、弱点や長所などを確認するために...

これは小さなプロジェクトであり、テストも同様に小さくする必要があることに注意してください。 (したがって、すべての厳密なテストは実行不可能です)

マンデルブローセットより正確にエスケープ時間アルゴリズム)を使用して、異なる言語のベンチマークを行います。
オリジナルのアルゴリズムは簡単に実装でき、そこからマルチスレッドバリアントを作成するのはそれほど面倒ではないので、私にはぴったりです。

以下は現在持っているコードです。まだシングルスレッドバリアントですが、結果に満足したらすぐに更新します。

#include <cstdlib> //for atoi
#include <iostream>
#include <iomanip> //for setw and setfill
#include <vector>


int DoThread(const double x, const double y, int maxiter) {
    double curX,curY,xSquare,ySquare;
    int i;

    curX = x + x*x - y*y;
    curY = y + x*y + x*y;
    ySquare = curY*curY;
    xSquare = curX*curX;

    for (i=0; i<maxiter && ySquare + xSquare < 4;i++) {
      ySquare = curY*curY;
      xSquare = curX*curX;
      curY = y + curX*curY + curX*curY;
      curX = x - ySquare + xSquare;
    }
    return i;
}

void SingleThreaded(int horizPixels, int vertPixels, int maxiter, std::vector<std::vector<int> >&  result) {
    for(int x = horizPixels; x > 0; x--) {
        for(int y = vertPixels; y > 0; y--) {
            //3.0 -> so we always have -1.5 -> 1.5 as the window; (x - (horizPixels / 2) will go from -horizPixels/2 to +horizPixels/2
            result[x-1][y-1] = DoThread((3.0 / horizPixels) * (x - (horizPixels / 2)),(3.0 / vertPixels) * (y - (vertPixels / 2)),maxiter);
        }
    }
}

int main(int argc, char* argv[]) {
    //first arg = length along horizontal axis
    int horizPixels = atoi(argv[1]);

    //second arg = length along vertical axis
    int vertPixels = atoi(argv[2]);

    //third arg = iterations
    int maxiter = atoi(argv[3]);

    //fourth arg = threads
    int threadCount = atoi(argv[4]);

    std::vector<std::vector<int> > result(horizPixels, std::vector<int>(vertPixels,0)); //create and init 2-dimensional vector
    SingleThreaded(horizPixels, vertPixels, maxiter, result);

    //TODO: remove these lines
    for(int y = 0; y < vertPixels; y++) {
      for(int x = 0; x < horizPixels; x++) {
            std::cout << std::setw(2) << std::setfill('0') << std::hex << result[x][y] << " ";
        }
        std::cout << std::endl;
    }
}

Linuxでgccを使用してテストしましたが、他のコンパイラ/オペレーティングシステムでも同様に動作するはずです。動作させるには、次のようなコマンドライン引数を入力する必要があります。

  

マンデルブロ106 106 500 255 1

最初の引数は幅(x軸)
2番目の引数は高さ(y軸)
3番目の引数は最大反復回数(色の数)
最後の要素はスレッドの数です(ただし、現在は使用されていません)

私の解像度では、上記の例はマンデルブロ集合の素敵なASCIIアート表現を与えてくれます。しかし、さまざまな引数を使って自分で試してみてください(最初の引数が最も重要な引数になります。これは幅になります)

以下で、pthreadの multi threaded パフォーマンスをテストするために一緒にハッキングしたコードを見つけることができます。まだクリーンアップしておらず、最適化も行われていません。そのため、コードは少しです。

ビットマップとして計算されたマンデルブロセットを保存するコードは私のものではありません。こちら

#include <cstdlib> //for atoi
#include <iostream>
#include <iomanip> //for setw and setfill
#include <vector>

#include "bitmap_Image.h" //for saving the mandelbrot as a bmp

#include <pthread.h>

pthread_mutex_t mutexCounter;
int sharedCounter(0);
int percent(0);

int horizPixels(0);
int vertPixels(0);
int maxiter(0);

//doesn't need to be locked
std::vector<std::vector<int> > result; //create 2 dimensional vector

void *DoThread(void *null) {
    double curX,curY,xSquare,ySquare,x,y;
    int i, intx, inty, counter;
    counter = 0;

    do {
        counter++;
        pthread_mutex_lock (&mutexCounter); //lock
            intx = int((sharedCounter / vertPixels) + 0.5);
            inty = sharedCounter % vertPixels;
            sharedCounter++;
        pthread_mutex_unlock (&mutexCounter); //unlock

        //exit thread when finished
        if (intx >= horizPixels) {
            std::cout << "exited thread - I did " << counter << " calculations" << std::endl;
            pthread_exit((void*) 0);
        }

        //set x and y to the correct value now -> in the range like singlethread
        x = (3.0 / horizPixels) * (intx - (horizPixels / 1.5));
        y = (3.0 / vertPixels) * (inty - (vertPixels / 2));

        curX = x + x*x - y*y;
        curY = y + x*y + x*y;
        ySquare = curY*curY;
        xSquare = curX*curX;

        for (i=0; i<maxiter && ySquare + xSquare < 4;i++){
          ySquare = curY*curY;
          xSquare = curX*curX;
          curY = y + curX*curY + curX*curY;
          curX = x - ySquare + xSquare;
        }
        result[intx][inty] = i;
     } while (true);
}

int DoSingleThread(const double x, const double y) {
    double curX,curY,xSquare,ySquare;
    int i;

    curX = x + x*x - y*y;
    curY = y + x*y + x*y;
    ySquare = curY*curY;
    xSquare = curX*curX;

    for (i=0; i<maxiter && ySquare + xSquare < 4;i++){
      ySquare = curY*curY;
      xSquare = curX*curX;
      curY = y + curX*curY + curX*curY;
      curX = x - ySquare + xSquare;
    }
    return i;

}

void SingleThreaded(std::vector<std::vector<int> >&  result) {
    for(int x = horizPixels - 1; x != -1; x--) {
        for(int y = vertPixels - 1; y != -1; y--) {
            //3.0 -> so we always have -1.5 -> 1.5 as the window; (x - (horizPixels / 2) will go from -horizPixels/2 to +horizPixels/2
            result[x][y] = DoSingleThread((3.0 / horizPixels) * (x - (horizPixels / 1.5)),(3.0 / vertPixels) * (y - (vertPixels / 2)));
        }
    }
}

void MultiThreaded(int threadCount, std::vector<std::vector<int> >&  result) {
    /* Initialize and set thread detached attribute */
    pthread_t thread[threadCount];
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);


    for (int i = 0; i < threadCount - 1; i++) {
        pthread_create(&thread[i], &attr, DoThread, NULL);
    }
    std::cout << "all threads created" << std::endl;

    for(int i = 0; i < threadCount - 1; i++) {
        pthread_join(thread[i], NULL);
    }
    std::cout << "all threads joined" << std::endl;
}

int main(int argc, char* argv[]) {
    //first arg = length along horizontal axis
    horizPixels = atoi(argv[1]);

    //second arg = length along vertical axis
    vertPixels = atoi(argv[2]);

    //third arg = iterations
    maxiter = atoi(argv[3]);

    //fourth arg = threads
    int threadCount = atoi(argv[4]);

    result = std::vector<std::vector<int> >(horizPixels, std::vector<int>(vertPixels,21)); // init 2-dimensional vector
    if (threadCount <= 1) {
        SingleThreaded(result);
    } else {
        MultiThreaded(threadCount, result);
    }


    //TODO: remove these lines
    bitmapImage image(horizPixels, vertPixels);
    for(int y = 0; y < vertPixels; y++) {
      for(int x = 0; x < horizPixels; x++) {
            image.setPixelRGB(x,y,16777216*result[x][y]/maxiter % 256, 65536*result[x][y]/maxiter % 256, 256*result[x][y]/maxiter % 256);
            //std::cout << std::setw(2) << std::setfill('0') << std::hex << result[x][y] << " ";
        }
        std::cout << std::endl;
    }

    image.saveToBitmapFile("~/Desktop/test.bmp",32);
}

次の引数を指定してプログラムを使用すると、良好な結果が得られます。

  

マンデルブロ5120 3840 256 3

そのようにすると、幅5 * 1024の画像が得られます。 5 * 768高、256色(alasは1または2のみを取得)および3スレッド(ワーカースレッドの作成以外の作業を行わない1つのメインスレッド、および2つのワーカースレッド)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top