2013-02-14 10 views
6

मैं समझता हूं कि ओपनएमपी वास्तव में केवल मैक्रोज़ का एक सेट है जो पठ्रेड में संकलित है। शेष संकलन होने से पहले पर्थ्रेड कोड देखने का कोई तरीका है? मैं संकलन करने के लिए जीसीसी का उपयोग कर रहा हूँ।pthreads में openmp संकलित करें सी कोड

उत्तर

8

पहला, ओपनएमपी मैक्रोज़ का एक साधारण सेट नहीं है। इसे पर्थ्रेड-जैसे कोड में एक सरल परिवर्तन देखा जा सकता है, लेकिन ओपनएमपी को रनटाइम समर्थन सहित उससे अधिक की आवश्यकता होती है।

कम से कम, जीसीसी में, आपके प्रश्न पर वापस, आप pthreaded कोड नहीं देख सकते हैं क्योंकि जीसीसी का ओपनएमपी कार्यान्वयन कंपाइलर बैक-एंड (या मध्य-अंत) में किया जाता है। परिवर्तन आईआर (मध्यवर्ती प्रतिनिधित्व) स्तर में किया जाता है। तो, प्रोग्रामर के दृष्टिकोण से, यह देखना आसान नहीं है कि कोड वास्तव में कैसे परिवर्तित होता है।

हालांकि, कुछ संदर्भ हैं।

(1) एक इंटेल इंजीनियर इंटेल C/C++ संकलक में OpenMP के कार्यान्वयन के एक महान सिंहावलोकन प्रदान:

http://www.drdobbs.com/parallel/how-do-openmp-compilers-work-part-1/226300148

http://www.drdobbs.com/parallel/how-do-openmp-compilers-work-part-2/226300277

(2) आप पर एक नज़र लग सकता है जीसीसी के OpenMP के कार्यान्वयन:

https://github.com/mirrors/gcc/tree/master/libgomp

देखें libgomp.h पाथ्रेड का उपयोग करता है, और loop.c समानांतर-लूप निर्माण के कार्यान्वयन में शामिल है।

-1

मैंने ओपनएमपी के साथ इसका परीक्षण नहीं किया है। लेकिन संकलक विकल्प -E आपको प्रीप्रोकैसिंग के बाद कोड देना चाहिए।

+0

ऐसा नहीं है। 'gcc -E' preprocessing करता है, लेकिन '# प्रगमा' की व्याख्या नहीं करता है, जो संकलन श्रृंखला में बहुत बाद में आता है। –

5

ओपनएमपी संकलक निर्देश का एक सेट है, मैक्रोज़ नहीं। सी/सी ++ में उन निर्देशों को #pragma विस्तार तंत्र के साथ कार्यान्वित किया जाता है जबकि फोर्ट्रान में उन्हें विशेष रूप से स्वरूपित टिप्पणियों के रूप में लागू किया जाता है। सीरियल कोड समानांतर में कनवर्ट करने के लिए ये निर्देश संकलक को कुछ कोड रूपांतरण निष्पादित करने का निर्देश देते हैं।

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

जीसीसी के साथ ओपनएमपी रूपांतरण के बाद कोड कैसा दिखता है, इसका एक स्यूडोकोड प्रस्तुत करना संभव है। आपको इसे -fdump-tree-all विकल्प प्रदान करना होगा, जिसके परिणामस्वरूप संकलक प्रत्येक संकलन इकाई के लिए बड़ी संख्या में इंटरमीडिएट फाइलों को फैलाएगा। सबसे दिलचस्प एक filename.017t.ompexp है (यह जीसीसी 4.7.1 से आता है, यह संख्या अन्य जीसीसी संस्करणों पर अलग हो सकती है, लेकिन एक्सटेंशन अभी भी .ompexp होगा)। ओपनएमपी संरचनाओं को कम करने के बाद इस फ़ाइल में कोड का मध्यवर्ती प्रतिनिधित्व होता है और फिर उनके उचित कार्यान्वयन में विस्तार किया जाता है।

void fun(double *data, int n) 
{ 
    #pragma omp parallel for 
    for (int i = 0; i < n; i++) 
    data[i] += data[i]*data[i]; 
} 

fun.c.017t.ompexp की सामग्री है:

fun (double * data, int n) 
{ 
    ... 
    struct .omp_data_s.0 .omp_data_o.1; 
    ... 

<bb 2>: 
    .omp_data_o.1.data = data; 
    .omp_data_o.1.n = n; 
    __builtin_GOMP_parallel_start (fun._omp_fn.0, &.omp_data_o.1, 0); 
    fun._omp_fn.0 (&.omp_data_o.1); 
    __builtin_GOMP_parallel_end(); 
    data = .omp_data_o.1.data; 
    n = .omp_data_o.1.n; 
    return; 
} 

fun._omp_fn.0 (struct .omp_data_s.0 * .omp_data_i) 
{ 
    int n [value-expr: .omp_data_i->n]; 
    double * data [value-expr: .omp_data_i->data]; 
    ... 

<bb 3>: 
    i = 0; 
    D.1637 = .omp_data_i->n; 
    D.1638 = __builtin_omp_get_num_threads(); 
    D.1639 = __builtin_omp_get_thread_num(); 
    ... 

<bb 4>: 
    ... this is the body of the loop ... 
    i = i + 1; 
    if (i < D.1644) 
    goto <bb 4>; 
    else 
    goto <bb 5>; 

<bb 5>: 

<bb 6>: 
    return; 

    ... 
} 

मैं संक्षिप्तता के लिए उत्पादन का बड़ा अंश नहीं दिखाए हैं

निम्न उदाहरण सी कोड, fun.c के रूप में सहेजा पर विचार करें। यह बिल्कुल सी कोड नहीं है। यह कार्यक्रम प्रवाह का सी-जैसा प्रतिनिधित्व है। <bb N> तथाकथित मूल ब्लॉक - कथन का संग्रह, प्रोग्राम के वर्कफ़्लो में एकल ब्लॉक के रूप में माना जाता है। पहली बात यह है कि कोई देखता है कि समांतर क्षेत्र एक अलग समारोह में निकाला जाता है। यह असामान्य नहीं है - अधिकांश ओपनएमपी कार्यान्वयन समान कोड रूपांतरण को कम या कम करते हैं। कोई यह भी देख सकता है कि कंपाइलर आवेषण libgompGOMP_parallel_start और GOMP_parallel_end जैसे कार्यों को बूटस्ट्रैप के लिए उपयोग किया जाता है और फिर समांतर क्षेत्र के निष्पादन को समाप्त करने के लिए (__builtin_ उपसर्ग बाद में हटा दिया जाता है) पर कॉल करता है। fun._omp_fn.0 के अंदर for लूप है, <bb 4> में लागू किया गया है (ध्यान दें कि लूप स्वयं भी विस्तारित है)। इसके अलावा सभी साझा चर को एक विशेष संरचना में रखा जाता है जो समांतर क्षेत्र के कार्यान्वयन के लिए पारित हो जाता है। <bb 3> में वह कोड है जो पुनरावृत्तियों की श्रृंखला की गणना करता है जिस पर वर्तमान थ्रेड संचालित होगा।

ठीक है, काफी सी कोड नहीं है, लेकिन यह शायद सबसे नज़दीकी चीज है जिसे कोई जीसीसी से प्राप्त कर सकता है।

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