문제

내가 지금하고있는 프로젝트 중 하나에 대해서 동시 활성화 프로그래밍 언어들.

현재 나는 비교를 찾고있다 스택이없는 파이썬 그리고 C ++ pthreads, 따라서이 두 언어에 중점을 두지 만 다른 언어는 나중에 테스트 될 것입니다. 물론 비교는 가능한 한 대표적이고 정확해야하므로 첫 번째 생각은 표준을 찾기 시작하는 것이 었습니다. 동시/다중 스레드 벤치 마크 문제, 아아 나는 괜찮은 또는 표준, 테스트/문제/벤치 마크를 찾을 수 없었습니다.

그래서 내 질문은 다음과 같습니다. 프로그래밍 언어의 성능을 테스트하기 위해 좋고 쉽게 또는 빠른 문제에 대한 제안이 있습니까? (그리고 과정에서 강력하고 약점을 드러내려면?

도움이 되었습니까?

해결책

벤치 마크 게임이 2008 년 9 월 쿼드 코어 머신으로 이동 한 이후, 다른 프로그래밍 언어의 많은 프로그램이 쿼드 코어를 이용하기 위해 다시 작성되었습니다. 예를 들어, 처음 10 개의 Mandelbrot 프로그램.

다른 팁

확실히 동시성 성능을위한 언어가 아닌 하드웨어 및 컴파일러를 테스트해야합니까?

나는 동시성 측면에서 얼마나 쉽고 생산적인 지에 대한 언어를보고 프로그래머가 잠금 실수를하는 것을 얼마나 '절연'하는지에 대한 언어를보고있을 것입니다.

편집 : 병렬 알고리즘을 설계하는 연구원으로서의 과거 경험에서, 대부분의 경우 동시 성능은 알고리즘이 평행을 이루는 방법과 그것이 기본 하드웨어를 목표로하는 방법에 크게 의존 할 것이라고 생각합니다.

또한 벤치 마크는 악명 높다. 이것은 평행 환경에서 더욱 그렇습니다. 예를 들어, '크런치'가 매우 큰 행렬이 벡터 파이프 라인 프로세서에 적합한 반면, 평행 한 종류는 더 범용 멀티 코어 CPU에 더 적합 할 수 있습니다.

유용 할 수 있습니다.

병렬 벤치 마크

NAS 병렬 벤치 마크

글쎄, 몇 가지 고전이 있지만 다른 테스트는 다른 기능을 강조합니다. 일부 분산 시스템은 더 강력하고 더 효율적인 메시지 통과 등을 가질 수 있습니다. 더 높은 메시지 오버 헤드는 확장 성을 해칠 수 있습니다. 더 많은 기계로 확장하는 일반적인 방법은 더 많은 수의 작은 메시지를 보내는 것이기 때문입니다. 당신이 시도 할 수있는 몇 가지 고전적인 문제는 Eratosthenes의 분산 체 또는 제대로 구현되지 않은 Fibonacci 시퀀스 계산기입니다 (즉, 시리즈의 8 번째 숫자, 7 번째 기계의 스핀, 6 위). 거의 모든 분할 및 정복 알고리즘을 동시에 수행 할 수 있습니다. Conway의 삶의 게임 또는 열전달을 동시에 구현할 수도 있습니다. 이러한 모든 알고리즘에는 초점이 다르기 때문에 하나의 분산 시스템이 모두 최선을 다하지 않을 것입니다.

나는 신속하게 구현하기 가장 쉬운 것이 제대로 구현되지 않은 Fibonacci 계산기라고 말하지만, 스레드를 생성하는 데 너무 중점을두고 그 스레드 사이의 통신에 너무 적은 것은 아닙니다.

확실히 동시성 성능을위한 언어가 아닌 하드웨어 및 컴파일러를 테스트해야합니까?

아니요, 하드웨어와 컴파일러는 테스트 목적과 관련이 없습니다. 한 언어로 작성된 코드가 다른 언어의 코드와 경쟁 할 수있는 방법을 테스트 할 수있는 몇 가지 좋은 문제를 찾고 있습니다. 동시 프로그래밍을 수행하기 위해 특정 언어로 사용 가능한 구성을 실제로 테스트하고 있습니다. 기준 중 하나는 성능 (정시 측정)입니다.

내가 찾고있는 다른 시험 기준 중 일부는 다음과 같습니다.

  • 어떻게 쉬운 올바른 코드를 작성하는 것입니까? 우리 모두가 동시 프로그래밍이 어렵다는 것을 알고 있기 때문에 단일 스레드 프로그램을 작성하는 것이 어렵 기 때문입니다.
  • 동시 프로그래밍에 사용 된 기술은 무엇입니까? 이벤트 중심, 배우 기반, 메시지 파싱, ...
  • 프로그래머 자신이 얼마나 많은 코드를 작성 해야하는지와 그에게 자동으로 수행되는 금액 : 주어진 벤치 마크 문제로 테스트 할 수도 있습니다.
  • 추상화 수준은 무엇이며 기계 코드로 다시 번역 될 때 얼마나 많은 오버 헤드가 관여하는지

사실, 나는 성능을 찾고 있지 않습니다 그만큼 Only and Best Parameter (실제로 언어 자체 대신 하드웨어 및 컴파일러로 나를 보낼 것입니다). 실제로 프로그래머 관점에서보고있는 언어는 어떤 종류의 문제에 가장 적합한 지, 약점이 무엇인지 확인합니다. 그리고 강점은 ...

이것은 단지 작은 프로젝트 일뿐 아니라 테스트도 작게 유지해야한다는 것을 명심하십시오. (따라서 모든 것에 대한 엄격한 테스트는 가능하지 않습니다)

나는 사용하기로 결정했다 만델 브로트 세트 (그만큼 탈출 시간 알고리즘 더 정확하게) 다른 언어를 벤치마킹하려면.
원래 알고리즘을 쉽게 구현할 수 있고 멀티 스레드 변형을 생성하는 것이 그다지 작동하지 않기 때문에 나에게 잘 어울립니다.

아래는 내가 현재 가지고있는 코드입니다. 여전히 단일 스레드 변형이지만 결과에 만족하자마자 업데이트하겠습니다.

#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로 테스트했지만 다른 컴파일러/운영 체제에서도 작동한다고 확신합니다. 작동하도록하려면 다음과 같은 명령 줄 인수를 입력해야합니다.

Mandelbrot 106 500 255 1

첫 번째 인수는 너비 (x 축)입니다.
두 번째 인수는 높이 (y 축)입니다.
세 번째 인수는 최대 반복 수 (색상 수)입니다.
마지막 ons는 스레드 수입니다 (그러나 현재 사용되지는 않습니다)

내 결의에서 위의 예는 Mandelbrot 세트의 멋진 ascii-art 표현을 제공합니다. 그러나 다른 논쟁으로 스스로 시도해보십시오 (첫 번째는 가장 중요한 것이 될 것입니다. 그것은 너비가 될 것입니다).

아래에서 당신은 내가 함께 해킹 한 코드를 찾을 수 있습니다. 멀티 스레드 pthreads의 성능. 나는 그것을 청소하지 않았으며 최적화가 이루어지지 않았습니다. 따라서 코드는 약간입니다 날것의.

비트 맵으로 계산 된 만델 브로트 세트를 저장하려는 코드는 비트 맵이 아닙니다. 여기

#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);
}

다음과 같은 인수와 함께 프로그램을 사용하여 좋은 결과를 얻을 수 있습니다.

Mandelbrot 5120 3840 256 3

그렇게하면 5 * 1024 너비의 이미지를 얻게됩니다. 5 * 768 높이는 256 개의 색상 (아시도 1 또는 2 만 얻을 수 있습니다)과 3 개의 스레드 (1 개의 메인 스레드 1 개는 작업자 스레드 생성을 제외하고는 작업을 수행하지 않는 1 개의 메인 스레드 및 2 개의 작업자 스레드)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top