Search code examples
cstaticopenmpfftw

Getting error when using FFTW plan as threadprivate


I am trying to use OpenMP on a code doing some complex algebra using FFTW operations. Each thread needs to work separately using its own work arrays. Therefore I followed this answer ( Reusable private dynamically allocated arrays in OpenMP ) and tried to use the threadprivate functionality. The FFTW plans and workspace variables need to be used many times in the code in multiple parallel segments.

The following is a test code. However, it gives all kinds of errors (segmentation faults, etc.) at the line p1=fftw_plan_ .... Any idea what I am doing wrong ? This seems to work well just with arrays but is not working for the FFTW plan. Can an FFTW plan be shared by threads but working on their separate data segments inpd, outc1, outc2 ?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
...
#include <math.h>
#include <complex.h>
#include <omp.h>
#include <fftw3.h>

int main(int argc, char *argv[])
{
    int npts2, id;
    
    static double *inpd;
    static fftw_complex *outc1, *outc2;
    static fftw_plan p1, p2;
    static int npts2stat;
    #pragma omp threadprivate(inpd,outc1,outc2,p1,p2,npts2stat)
    
    npts2=1000;
    
    #pragma omp parallel private(id) shared(npts2)
    {
        id=omp_get_thread_num();
        printf("Thread %d: Allocating threadprivate memory \n",id);
        
        npts2stat=npts2;
        
        printf("step1 \n");
        inpd=malloc(sizeof(double)*npts2stat);
        outc1=fftw_malloc(sizeof(fftw_complex)*npts2stat);
        outc2=fftw_malloc(sizeof(fftw_complex)*npts2stat);
        printf("step2 \n");
        // CODE COMPILES FINE BUT STOPS HERE WITH ERROR
        p1=fftw_plan_dft_r2c_1d(npts2stat,inpd,outc1,FFTW_ESTIMATE);
        p2=fftw_plan_dft_1d(npts2stat,outc1,outc2,FFTW_BACKWARD,FFTW_ESTIMATE);
        printf("step3 \n");
    }
    
    // multiple omp parallel segments with different threads doing some calculations on complex numbers using FFTW
    
    #pragma omp parallel private(id)
    {
        id=omp_get_thread_num();
        printf("Thread %d: Deallocating threadprivate memory \n",id);
        free(inpd);
        fftw_free(outc1);
        fftw_free(outc2);
        fftw_destroy_plan(p1);
        fftw_destroy_plan(p2);
    }
}

EDIT1: I seem to have solved the segmentation fault issue below. However if you have a better way of doing this, that will be helpful. For example, I don't know if a single plan for all threads is sufficient because it is acting on different data inpd private to different threads.


Solution

  • Sorry the section on Thread Safety in FFTW manual makes it pretty clear that FFTW planner should be called only one thread at a time. This seems to have solved the segmentation fault issue.

    #pragma omp critical
            {
            p1=fftw_plan_dft_r2c_1d(npts2stat,inpd,outc1,FFTW_ESTIMATE);
            p2=fftw_plan_dft_1d(npts2stat,outc1,outc2,FFTW_BACKWARD,FFTW_ESTIMATE);
            }