जीसीसी वेक्टरिसर में एक कमी है जो हाल ही के जीसीसी संस्करणों में हल किया गया प्रतीत होता है। अपने परीक्षण मामले जीसीसी 4.7.2 vectorises सफलतापूर्वक निम्नलिखित सरल पाश में:
एक ही समय जीसीसी 4.6.1 में नहीं है और यह शिकायत करता है, पाश फ़ंक्शन को कॉल या डेटा संदर्भ का विश्लेषण किया नहीं किए जा सकते हैं। वेक्टरिसर में बग parallel for
लूप जीसीसी द्वारा लागू किए जाने के तरीके से ट्रिगर किया जाता है।OpenMP निर्माणों संसाधित और विस्तार कर रहे हैं, सरल पाश कोड इस के लिए कुछ सदृश में तब्दील हो जाता:
struct omp_fn_0_s
{
int N;
double *a;
double *b;
double *c;
double d;
};
void omp_fn_0(struct omp_fn_0_s *data)
{
int start, end;
int nthreads = omp_get_num_threads();
int threadid = omp_get_thread_num();
// This is just to illustrate the case - GCC uses a bit different formulas
start = (data->N * threadid)/nthreads;
end = (data->N * (threadid+1))/nthreads;
for (int i = start; i < end; i++)
data->a[i] = data->b[i] + data->c[i] * data->d;
}
...
struct omp_fn_0_s omp_data_o;
omp_data_o.N = N;
omp_data_o.a = a;
omp_data_o.b = b;
omp_data_o.c = c;
omp_data_o.d = d;
GOMP_parallel_start(omp_fn_0, &omp_data_o, 0);
omp_fn_0(&omp_data_o);
GOMP_parallel_end();
N = omp_data_o.N;
a = omp_data_o.a;
b = omp_data_o.b;
c = omp_data_o.c;
d = omp_data_o.d;
जीसीसी में vectoriser 4.7 से पहले कि पाश vectorise करने में विफल रहता। यह ओपनएमपी-विशिष्ट समस्या नहीं है। कोई आसानी से इसे ओपनएमपी कोड के साथ पुन: पेश नहीं कर सकता है। - क्योंकि निर्दिष्ट करने के लिए है कि कोई अलियासिंग हो सकता है इस्तेमाल किया restrict
कीवर्ड की समान रूप से अच्छी तरह से vectorise चाहिए
struct fun_s
{
double *restrict a;
double *restrict b;
double *restrict c;
double d;
int n;
};
void fun1(double *restrict a,
double *restrict b,
double *restrict c,
double d,
int n)
{
int i;
for (i = 0; i < n; i++)
a[i] = b[i] + c[i] * d;
}
void fun2(struct fun_s *par)
{
int i;
for (i = 0; i < par->n; i++)
par->a[i] = par->b[i] + par->c[i] * par->d;
}
एक उम्मीद होती है कि दोनों कोड (! कोई OpenMP यहाँ नोटिस): इस बात की पुष्टि करने के लिए मैं निम्नलिखित साधारण परीक्षण लिखा था। दुर्भाग्यवश यह GCC < 4.7 के साथ मामला नहीं है - यह fun1
में लूप को सफलतापूर्वक वेक्टर करता है लेकिन fun2
में वक्रता को विफल करने में विफल रहता है जब यह ओपनएमपी कोड को संकलित करता है।
इस का कारण यह है कि vectoriser साबित होता है कि par->d
में असमर्थ है-स्मृति में है कि par->a
, par->b
, और par->c
बिंदु से झूठ नहीं करता है। यह हमेशा fun1
के साथ मामला है, जहां दो मामलों संभव हो रहे हैं नहीं है:
d
एक रजिस्टर में एक मूल्य के तर्क के रूप में पारित हो जाता है;
d
स्टैक पर एक मूल्य तर्क के रूप में पारित किया गया है।
x64 सिस्टम पर सिस्टम वी एबीआई अनिवार्य है कि एक्सएमएम रजिस्टरों (एवीएक्स-सक्षम CPUs पर वाईएमएम) में पहले कई फ़्लोटिंग-पॉइंट तर्क पारित किए जाते हैं। इस प्रकार d
इस मामले में पारित हो जाता है और इसलिए कोई सूचक कभी भी इंगित नहीं कर सकता - लूप को वेक्टरिज्ड हो जाता है। X86 सिस्टम पर एबीआई अनिवार्य है कि तर्क स्टैक पर पारित किए जाते हैं, इसलिए d
को तीन बिंदुओं में से किसी एक द्वारा अलिया किया जा सकता है। दरअसल, -m32
विकल्प के साथ 32-बिट x86 कोड उत्पन्न करने के निर्देश दिए जाने पर जीसीसी fun1
में लूप को सदिश करने से इंकार कर देता है।
जीसीसी 4.7 रन-टाइम चेक डालने से इसके आसपास हो जाता है जो सुनिश्चित करता है कि न तो d
और न ही par->d
उपनाम प्राप्त करें।
d
से छुटकारा unprovable गैर अलियासिंग दूर करता है और निम्नलिखित OpenMP कोड जीसीसी 4.6.1 द्वारा vectorised हो जाता है:
#pragma omp parallel for schedule(static)
for (int i = 0; i < N; i++)
a[i] = b[i] + c[i];
मुझे लगता है कि आप इस प्रश्न में [answer] (http://stackoverflow.com/a/14717689/771663) में समझदार जानकारी पा सकते हैं। – Massimiliano
धन्यवाद, यह बताता है कि ओपनएमपी के साथ सिमड का उपयोग कैसे करें, लेकिन ऐसा लगता है कि जब मैं ओपनएमपी का उपयोग करता हूं तो सिम स्टॉप के पहले से ही काम करने के कार्यान्वयन का काम क्यों नहीं कर रहा है। क्या दोनों का उपयोग करने का कोई तरीका नहीं है? – superbriggs
यह भी दर्शाता है कि मैं केवल बिट्स की संख्या पर ही काम कर सकता हूं, वे सिर्फ संख्याओं के बीच विभाजित हैं। जीसीसी के साथ ऐसा करने पर मुझे नहीं पूछा गया कि मैं कितने रजिस्टर पर विभाजन करना चाहता हूं। चूंकि मैं एक विश्वविद्यालय 'सुपर कंप्यूटर' का उपयोग कर रहा हूं, मैंने सोचा था कि हार्डवेयर हेम सिम के लिए अतिरिक्त रिक्त स्थान है। अगर मैं सही हूं तो मुझे कैसे पता चलेगा? – superbriggs