FFTW3 - распараллеливание 1D на месте сложного БПФ происходит медленно - PullRequest
0 голосов
/ 20 февраля 2019

Так что я работаю над распараллеливанием 1D FFT.В качестве первой задачи я выполнил сравнительный анализ библиотеки FFTW3 на процессоре Intel® Xeon® R E5-2620 v3 @ 2,40 ГГц , который имеет 16 ядер.Я только что сделал базовое 1D Complex FFT с OpenMP в качестве моей библиотеки потоков.Я скомпилировал на ICC, используя следующую команду:

icc -Wall -Werror
-I/.../mkl/include -I/apps/intel/linux/mkl/include/fftw  
fftw3_dft.c   
-L/.../intel/linux/mkl/.../intel64 -lmkl_rt 
-L/.../intel/.../linux/mkl/../compiler/lib/intel64 
-L/apps/intel/.../clinux/mkl/../tbb/lib/intel64/gcc4.4 
-liomp5 -lm -lpthread -ldl 
 -o fftw3_dft.out

Я рассчитал показатель ускорения для разных размеров задач.Я не могу объяснить этот график

  • Для задач размером от 2 ^ 21 до 2 ^ 24, почему нет ускорения при использовании 2 процессоров? (Даже если естьнекоторое ускорение для потоков 4,8 и 16)
  • Почему происходит внезапное увеличение ускорения, когда размер проблемы становится больше 2 ^ 27?

Speedup vs problem size graph

код

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>

#include "fftw3.h"
#include "mkl.h"

/* Compute (K*L)%M accurately */
static double moda(int K, int L, int M)
{
    return (double)(((long long)K * L) % M);
}

/* Initialize array x[N] with harmonic H */
static void init(fftw_complex *x, int N, int H)
{
    double TWOPI = 6.2831853071795864769, phase;
    int n;

    for (n = 0; n < N; n++)
    {
         phase  = moda(n,H,N) / N;
         x[n][0] = cos( TWOPI * phase ) / N;
        x[n][1] = sin( TWOPI * phase ) / N;
    }
}

int main(int argc, char *argv[]) {

    if(argc < 3) {
         printf("Error : give args\n");
        return 0;
     }


int N = atoi(argv[1]);
int p = atoi(argv[2]);

int H =  -N/2;
fftw_plan forward_plan = 0, backward_plan = 0;
fftw_complex *x = 0;
int status = 0;

fftw_init_threads();
fftw_plan_with_nthreads(p);

x  = fftw_malloc(sizeof(fftw_complex)*N);

forward_plan = fftw_plan_dft(1, &N, x, x, FFTW_FORWARD, FFTW_ESTIMATE);

init(x, N, H);

double start_time = dsecnd();

/*--------------ALG STARTS HERE --------------------------*/
fftw_execute(forward_plan);
/*--------------ALG ENDS HERE --------------------------*/

double end_time = dsecnd();

printf(LI", %d, %lf\n", N, p, end_time - start_time);
fftw_cleanup_threads()
fftw_destroy_plan(forward_plan);
fftw_free(x);

}

1 Ответ

0 голосов
/ 28 февраля 2019

Я получаю ускорение для 2 ядер даже при n = 2 ^ 14, и после этого оно остается стабильно выше 1,5.Не забудьте запустить код несколько раз и выбросить первую часть, использованную для раскрутки.Современным ядрам нужно некоторое время, чтобы набрать полную скорость.

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>

#include "fftw3.h"
#include "omp.h"

/* Compute (K*L)%M accurately */
static double moda(int K, int L, int M)
{
    return (double)(((long long)K * L) % M);
}

/* Initialize array x[N] with harmonic H */
static void init(fftw_complex *x, int N, int H)
{
    double TWOPI = 6.2831853071795864769, phase;
    int n;

    for (n = 0; n < N; n++)
    {
         phase  = moda(n,H,N) / N;
         x[n][0] = cos( TWOPI * phase ) / N;
        x[n][1] = sin( TWOPI * phase ) / N;
    }
}

int main(int argc, char *argv[]) {

    if(argc < 2) {
         printf("Error : give args\n");
        return 0;
     }


int max_pow = atoi(argv[1]);
int p = 1;
#pragma omp parallel
{
#pragma omp single
{
  p = omp_get_num_threads();
}
}
printf("%i\n", p);

fftw_plan forward_plan = 0;
fftw_complex *x = 0;

fftw_init_threads();
fftw_plan_with_nthreads(p);

for(int iter=1;iter<=2;iter++){
  //throw away the first round, a couple of seconds is enough
  for(int pw=12;pw<=max_pow;pw++){
    int N = pow(2, pw);
    int H =  -N/2;

    x  = fftw_malloc(sizeof(fftw_complex)*N);

    forward_plan = fftw_plan_dft(1, &N, x, x, FFTW_FORWARD, FFTW_MEASURE);

    init(x, N, H);

    double start_time = omp_get_wtime();

    /*--------------ALG STARTS HERE --------------------------*/
    for(int i=1;i<=5;i++){fftw_execute(forward_plan);}
    /*--------------ALG ENDS HERE --------------------------*/

    double end_time = omp_get_wtime();

    printf("%i %lf\n", pw, (end_time - start_time)/5);
    fftw_destroy_plan(forward_plan);
    fftw_free(x);
  }
}

return 0;
}

и

> gfortran -fopenmp fftw1d.c -lfftw3 -lfftw3_omp
> OMP_NUM_THREADS=2 ./a.out 24

результаты совпадают с -O3 и без него, поскольку библиотека уже скомпилирована.

enter image description here

Протестировано на четырехъядерном процессоре Intel (R) Core (TM) i7-3770 @ 3,40 ГГц

...