2013-02-21 11 views
5

का उपयोग कर एफएफटीडब्ल्यू योजना निर्माण मैं समानांतर में कई एफएफटी करने की कोशिश कर रहा हूं। मैं एफएफटीडब्ल्यू और ओपनएमपी का उपयोग कर रहा हूं। प्रत्येक एफएफटी अलग है, इसलिए मैं एफएफटीडब्ल्यू के बिल्ड-इन मल्टीथ्रेडिंग (जो मुझे पता है ओपनएमपी का उपयोग करता है) पर निर्भर नहीं है।ओपनएमपी

int m; 

// assume: 
// int numberOfColumns = 100; 
// int numberOfRows = 100; 

#pragma omp parallel for default(none) private(m) shared(numberOfColumns, numberOfRows)// num_threads(4) 
    for(m = 0; m < 36; m++){ 

     // create pointers 
     double   *inputTest; 
     fftw_complex *outputTest; 
     fftw_plan  testPlan; 

     // preallocate vectors for FFTW 
     outputTest = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*numberOfRows*numberOfColumns); 
     inputTest = (double *)fftw_malloc(sizeof(double)*numberOfRows*numberOfColumns); 

     // confirm that preallocation worked 
     if (inputTest == NULL || outputTest == NULL){ 
      logger_.log_error("\t\t FFTW memory not allocated on m = %i", m); 
     } 

     // EDIT: insert data into inputTest 
     inputTest = someDataSpecificToThisIteration(m); // same size for all m 

     // create FFTW plan 
     #pragma omp critical (make_plan) 
     { 
      testPlan = fftw_plan_dft_r2c_2d(numberOfRows, numberOfColumns, inputTest, outputTest, FFTW_ESTIMATE); 
     } 

     // confirm that plan was created correctly 
     if (testPlan == NULL){ 
      logger_.log_error("\t\t failed to create plan on m = %i", m); 
     } 

     // execute plan 
     fftw_execute(testPlan); 

     // clean up 
     fftw_free(inputTest); 
     fftw_free(outputTest); 
     fftw_destroy_plan(testPlan); 

    }// end parallelized for loop 

यह सब ठीक काम करता है। हालांकि, अगर मैं योजना निर्माण (fftw_plan_dft_r2c_2d) के आसपास से महत्वपूर्ण निर्माण को हटा देता हूं तो मेरा कोड विफल हो जाएगा। क्या कोई समझा सकता है क्यों? fftw_plan_dft_r2c_2d वास्तव में एक "अनाथ" नहीं है, है ना? क्या ऐसा इसलिए है क्योंकि दो थ्रेड दोनों संख्या ओफ्रो या संख्या ओफ कॉलम स्मृति स्थान को एक ही समय में हिट करने का प्रयास कर सकते हैं?

+0

आप fftw की बहु-थ्रेडिंग क्षमताओं का उपयोग नहीं कर रहे हैं। आप वास्तव में समानांतर में 36 सिंगल-थ्रेडेड ट्रांसफॉर्म बना रहे हैं। –

+0

मुझे पता है। मैं कहता हूं कि मेरे शुरुआती प्रश्न में * प्रत्येक एफएफटी अलग है, इसलिए मैं एफएफटीडब्ल्यू के बिल्ड-इन मल्टीथ्रेडिंग_ पर भरोसा नहीं कर रहा हूं। मैं समानांतर में 36 सिंगल-थ्रेडेड ट्रांसफॉर्मेशन बनाना चाहता हूं। – tir38

+0

क्षमा करें, मेरी गलती, मैंने बिल्कुल विपरीत पढ़ा ;-) –

उत्तर

7

यह बहुत ज्यादा सब FFTW प्रलेखन के बारे में thread safety में लिखा है:

... लेकिन कुछ ध्यान रखा जाना चाहिए क्योंकि योजनाकार दिनचर्या शेयर डेटा (जैसे बुद्धि और त्रिकोणमितीय तालिकाओं) कॉल और योजनाओं के बीच।

ऊपर की ओर यह है कि एफएफटीडब्ल्यू में एकमात्र थ्रेड-सुरक्षित (पुनः प्रवेश) दिनचर्या fftw_execute (और इसके नए सरणी प्रकार) हैं। अन्य सभी दिनचर्या (जैसे प्लानर) को एक समय में केवल एक थ्रेड से ही बुलाया जाना चाहिए। तो, उदाहरण के लिए, आप योजनाकार को किसी भी कॉल के आस-पास एक सेमफोर लॉक लपेट सकते हैं; और भी आसान, आप केवल एक थ्रेड से अपनी सभी योजनाएं बना सकते हैं। हमें नहीं लगता कि यह एक महत्वपूर्ण प्रतिबंध होना चाहिए (एफएफटीडब्ल्यू उस स्थिति के लिए डिज़ाइन किया गया है जहां एकमात्र प्रदर्शन-संवेदनशील कोड ट्रांसफॉर्म का वास्तविक निष्पादन है), और योजनाओं के बीच साझा डेटा के लाभ बहुत अच्छे हैं।

एफएफटी योजनाओं के एक सामान्य अनुप्रयोग में शायद ही कभी निर्माण किया जाता है, इसलिए इससे कोई फर्क नहीं पड़ता कि आपको उनकी रचना को सिंक्रनाइज़ करना है या नहीं। आपके मामले में आपको प्रत्येक पुनरावृत्ति पर एक नई योजना बनाने की आवश्यकता नहीं है, जब तक कि डेटा का आयाम बदल न जाए।

#pragma omp parallel default(none) private(m) shared(numberOfColumns, numberOfRows) 
{ 
    // create pointers 
    double   *inputTest; 
    fftw_complex *outputTest; 
    fftw_plan  testPlan; 

    // preallocate vectors for FFTW 
    outputTest = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*numberOfRows*numberOfColumns); 
    inputTest = (double *)fftw_malloc(sizeof(double)*numberOfRows*numberOfColumns); 

    // confirm that preallocation worked 
    if (inputTest == NULL || outputTest == NULL){ 
     logger_.log_error("\t\t FFTW memory not allocated on m = %i", m); 
    } 

    // create FFTW plan 
    #pragma omp critical (make_plan) 
    testPlan = fftw_plan_dft_r2c_2d(numberOfRows, numberOfColumns, inputTest, outputTest, FFTW_ESTIMATE); 

    #pragma omp for 
    for (m = 0; m < 36; m++) { 
     // execute plan 
     fftw_execute(testPlan); 
    } 

    // clean up 
    fftw_free(inputTest); 
    fftw_free(outputTest); 
    fftw_destroy_plan(testPlan); 
} 

अब योजनाओं प्रत्येक धागा और क्रमबद्धता भूमि के ऊपर fftw_execute() में से प्रत्येक के निष्पादन के साथ कम होता में केवल एक बार बनाई गई हैं: आप बल्कि निम्नलिखित करना होगा। यदि NUMA सिस्टम पर चल रहा है (उदा। बहु-सॉकेट AMD64 या इंटेल (पोस्ट-) नेहलेम सिस्टम), तो आपको अधिकतम प्रदर्शन प्राप्त करने के लिए थ्रेड बाध्यकारी सक्षम करना चाहिए।

+0

मैंने मैनुअल के उस भाग को पढ़ा ... मैं अपने प्रश्न का उत्तर देने के लिए वापस आया और तुम्हारा देखा। आपको चेक मिलती है। आप कहते हैं "जब तक डेटा का आयाम बदलता नहीं है" लेकिन क्या होगा यदि आयाम समान हैं लेकिन मान अलग हैं? मैंने इसे प्रतिबिंबित करने के लिए अपना मूल प्रश्न अपडेट किया। – tir38

+0

@ tir38, यही कारण है कि आप कई बार योजना निष्पादित करते हैं, है ना? जब तक आप इनपुट और आउटपुट सरणी का पुन: उपयोग करते हैं तब तक एक भी योजना ठीक है। बस 'inputTest' को असाइन न करें क्योंकि यह एक सूचक है। आपके पास 'someDataSpecificToThisIteration (m, inputData)' की तरह कुछ होगा और फ़ंक्शन से आउटपुट को 'इनपुटडेटा' में रखा जाएगा। –

+0

क्षमा करें फिर से। मेरा मतलब था 'someDataSpecificToThisIteration [m] '। यह एक विधि कॉल नहीं है, लेकिन कुछ सामान्य सरणी से एक खींच है। तो मैं सिर्फ उस डेटा के लिए इनपुट इनपुट 'इनपुटडाटा' कर रहा हूं। क्योंकि मेरे पास 36 सरणी प्रविष्टियों के प्रभावी ढंग से 36 पॉइंटर्स हैं, मुझे 36 योजनाओं की आवश्यकता है, है ना? – tir38

संबंधित मुद्दे