Pergunta

Para um dos projetos que estou fazendo agora, eu preciso olhar para o desempenho (entre outras coisas) de diferentes concorrente habilitado linguagens de programação .

No momento eu estou olhando para comparar stackless python e PThreads C ++ , então o foco é sobre estas duas línguas, mas outras línguas provavelmente será testado mais tarde. Claro que a comparação deve ser o mais representativo e preciso quanto possível, assim que meu primeiro pensamento foi para começar a procurar algum padrão concomitante / problemas de benchmark multi-threaded , infelizmente eu não podia encontrar, testes / problemas / benchmarks decentes ou padrão.

Então, minha pergunta é a seguinte: Você tem uma sugestão para uma boa, problema fácil ou rápido para testar o desempenho da linguagem de programação (e expô-la é pontos fortes e fracos no processo )?

Foi útil?

Solução

Uma vez que o jogo benchmarks mudou-se para uma máquina quad-core setembro de 2008, muitos programas em diferentes linguagens de programação foram re-escrito para explorar quad-core - por exemplo, os primeiros 10 programas mandelbrot .

Outras dicas

Com certeza você deve estar testando hardware e compiladores, em vez de um idioma para o desempenho de simultaneidade?

Eu estaria olhando para um idioma a partir do ponto de vista de como é fácil e produtivo é em termos de concorrência e quanto ele 'isola' o programador de cometer erros de bloqueio.

EDIT: a experiência do passado como pesquisador projetar algoritmos paralelos, eu acho que você vai encontrar na maioria dos casos o desempenho simultâneo dependerá em grande parte como um algoritmo é paralelizado, e como ele atinge o hardware subjacente.

Além disso, benchmarks são notoriamente desigual; este é ainda mais em um ambiente paralelo. Por exemplo, uma referência que 'flexões' muito grandes matrizes seria adequado para um processador pipeline de vetor, enquanto uma espécie paralelo poderia ser mais adequado para uso mais geral CPUs multi core.

Estes podem ser úteis:

Parallel Benchmarks

NAS Parallel Benchmarks

Bem, há alguns clássicos, mas diferentes testes enfatizar características diferentes. Alguns sistemas distribuídos podem ser mais robusto, tem mais eficientes, etc. mensagem de sobrecarga Superior de passagem de mensagens pode machucar a escalabilidade, uma vez que o caminho normal para escalar até mais máquinas é enviar um número maior de pequenas mensagens. Alguns problemas clássicos que você pode tentar são a Sieve distribuída de Eratóstenes ou uma calculadora seqüência de Fibonacci mal implementado (ou seja, para calcular o número 8º na série, rotação de uma máquina para a 7ª, e outro para a 6ª). Praticamente qualquer algoritmo de divisão e conquista pode ser feito simultaneamente. Você também pode fazer uma implementação simultânea de jogo de vida ou de transferência de calor de Conway. Note-se que todos estes algoritmos têm focos diferentes e, portanto, você provavelmente não terá um sistema distribuído fazendo o melhor em todos eles.

Eu diria que o mais fácil de implementar rapidamente é a calculadora de Fibonacci mal implementado, embora ele coloca muita ênfase em tópicos criando e muito pouco na comunicação entre esses segmentos.

hardware

Certamente você deve estar testando e compiladores, em vez de uma linguagem para o desempenho de simultaneidade?

Não, hardware e compiladores são irrelevantes para os meus fins de teste. Eu só estou procurando alguns bons problemas que podem testar como código bem, escrito em um idioma, pode competir contra código de outro idioma. Estou realmente testar as construções disponível nos idiomas específicos para fazer programação concorrente. E um dos critérios é o desempenho (medido em tempo).

Alguns dos outros critérios de teste que eu estou procurando são:

  • como fácil é para escrever código correto; porque como todos sabemos programação concorrente é mais difícil, então escrever programas single threaded
  • o que é a técnica utilizada para a programação concorrente: event-driven, ator base, mensagem de análise, ...
  • a quantidade de código deve ser escrito pelo próprio programador e quanto é feito automaticamente para ele: isso também pode ser testado com os dados problemas de benchmark
  • qual é o nível de abstração e quanto sobrecarga está envolvido quando traduzido de volta para código de máquina

Então, na verdade, eu não estou olhando para o desempenho como o única e melhor parâmetro (o que de fato me mandar para o hardware e os compiladores, em vez do próprio idioma), na verdade estou procurando de um programadores ponto de vista de verificar o que a linguagem é mais adequado para o tipo de problemas, o que é pontos fracos e fortes são e assim por diante ...

Bare em mente que este é apenas um pequeno projeto e os testes são, portanto, ser mantido pequeno também. (Testes rigorosos de tudo não é, portanto, possível)

Eu decidi usar o Mandelbrot conjunto (o escape em tempo algoritmo para ser mais preciso) para aferir as diferentes línguas.
Ele me se encaixa muito bem como o algoritmo original pode ser facilmente implementado e criando a variante multi threaded dele não é que muito trabalho.

abaixo é o código que eu tenho atualmente. É ainda uma única variante de rosca, mas vou atualizá-lo assim que eu estou satisfeito com o resultado.

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

Eu testei com gcc no Linux, mas eu tenho certeza que ele trabalha sob outros compiladores / Sistemas operacionais também. Para fazê-lo funcionar você tem que digitar alguns argumentos de linha de comando da seguinte forma:

mandelbrot 106 500 255 1

o primeiro argumento é o (x-eixo) largura
o segundo argumento é a altura (eixo y)
O terceiro argumento é o número máximo de iterações (o número de cores)
os últimos ons é o número de threads (mas aquele momento não é usado)

na minha resolução, o exemplo acima me dá uma boa representação ASCII-art de um conjunto de Mandelbrot. Mas experimentar por si próprio com argumentos diferentes (o primeiro será o mais importante, como que vai ser a largura)

Abaixo, você pode encontrar o código que eu cortei juntos para testar a multi threaded desempenho de pthreads. Eu não limpa-lo e sem otimizações foram feitas; de modo que o código é um pouco raw .

O código para salvar o conjunto de Mandelbrot calculado como um mapa de bits não é minha, você pode encontrá-lo aqui

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

bons resultados podem ser obtidos utilizando o programa com os seguintes argumentos:

mandelbrot 5120 3840 256 3

dessa forma você terá uma imagem que é de 5 * 1024 de largura; 5 * 768 de alta com 256 cores (infelizmente você só vai conseguir 1 ou 2) e 3 segmentos (1 thread principal que não fazer qualquer trabalho, exceto criar os segmentos de trabalho, e 2 threads de trabalho)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top