Низкая производительность в программе OpenMP - PullRequest
3 голосов
/ 22 декабря 2010

Я пытаюсь понять код openmp из здесь .Вы можете увидеть код ниже.

  1. Чтобы измерить ускорение, разницу между последовательной версией и версией omp, я использую time.h, вы находите правильный подход?

  2. Программа работает на 4-ядерном компьютере.Я указываю export OMP_NUM_THREADS="4", но не вижу значительного ускорения, обычно я получаю 1,2 - 1,7.С какими проблемами я сталкиваюсь в этом распараллеливании?

  3. Какой инструмент отладки / производительности я мог бы использовать, чтобы увидеть потерю производительности?

код (для компиляции я использую xlc_r -qsmp=omp omp_workshare1.c -o omp_workshare1.exe)

#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#define CHUNKSIZE   1000000
#define N       100000000

int main (int argc, char *argv[]) 
{
    int nthreads, tid, i, chunk;
    float a[N], b[N], c[N];
    unsigned long elapsed;
    unsigned long elapsed_serial;
    unsigned long elapsed_omp;
    struct timeval start;
    struct timeval stop;


    chunk = CHUNKSIZE;

    // =================    SERIAL     start =======================
    /* Some initializations */
    for (i=0; i < N; i++)
        a[i] = b[i] = i * 1.0;
    gettimeofday(&start,NULL); 
    for (i=0; i<N; i++)
    {
        c[i] = a[i] + b[i];
        //printf("Thread %d: c[%d]= %f\n",tid,i,c[i]);
    }
    gettimeofday(&stop,NULL);
    elapsed = 1000000 * (stop.tv_sec - start.tv_sec);
    elapsed += stop.tv_usec - start.tv_usec;
    elapsed_serial = elapsed ;
    printf ("   \n Time SEQ= %lu microsecs\n", elapsed_serial);
    // =================    SERIAL     end =======================


    // =================    OMP    start =======================
    /* Some initializations */
    for (i=0; i < N; i++)
        a[i] = b[i] = i * 1.0;
    gettimeofday(&start,NULL); 
#pragma omp parallel shared(a,b,c,nthreads,chunk) private(i,tid)
    {
        tid = omp_get_thread_num();
        if (tid == 0)
        {
            nthreads = omp_get_num_threads();
            printf("Number of threads = %d\n", nthreads);
        }
        //printf("Thread %d starting...\n",tid);

#pragma omp for schedule(static,chunk)
        for (i=0; i<N; i++)
        {
            c[i] = a[i] + b[i];
            //printf("Thread %d: c[%d]= %f\n",tid,i,c[i]);
        }

    }  /* end of parallel section */
    gettimeofday(&stop,NULL);
    elapsed = 1000000 * (stop.tv_sec - start.tv_sec);
    elapsed += stop.tv_usec - start.tv_usec;
    elapsed_omp = elapsed ;
    printf ("   \n Time OMP= %lu microsecs\n", elapsed_omp);
    // =================    OMP    end =======================
    printf ("   \n speedup= %f \n\n", ((float) elapsed_serial) / ((float) elapsed_omp)) ;

}

1 Ответ

1 голос
/ 23 декабря 2010

В коде, описанном выше, нет ничего плохого, но ваше ускорение будет ограничено тем, что основной цикл c = a + b выполняет очень мало работы - время, необходимое для выполнения вычислений (a одно добавление) будет зависеть от времени доступа к памяти (2 загрузки и одно хранилище), и будет больше конкуренции за пропускную способность памяти с большим количеством потоков, действующих на массив.

Мы можем проверить это, сделав работу внутри цикла более ресурсоемкой:

c[i] = exp(sin(a[i])) + exp(cos(b[i]));

И тогда мы получим

$ ./apb

 Time SEQ= 17678571 microsecs
Number of threads = 4

 Time OMP= 4703485 microsecs

 speedup= 3.758611 

, что, очевидно, намного ближе к 4-кратному ускорению, которое можно ожидать.

Обновление: Да, и к другим вопросам - gettimeofday (), вероятно, подходит для синхронизации, а в системе, где вы используете xlc - это AIX? В этом случае peekperf является хорошим инструментом для повышения общей производительности, а аппаратные мониторы производительности предоставят вам доступ к времени доступа к памяти. На платформах x86 бесплатные инструменты для мониторинга производительности многопоточного кода включают cachegrind / valgrind для отладки производительности кэша (здесь не проблема), scalasca для общих проблем с OpenMP и OpenSpeedShop, также довольно полезный.

...