2013-07-27 5 views
5

OpenCL में, READ_ONLY या WRITE_ONLY के रूप में बफर को फ़्लैग करने के लिए कोई प्रदर्शन लाभ है?ओपनसीएल - क्यों READ_ONLY या WRITE_ONLY बफर का उपयोग करें

यह kernel क्या मैं अक्सर (WRITE_ONLY एक READ_ONLY और ख है) देखते हैं:

__kernel void two_buffer_double(__global float* a, __global float* b) 
{ 
    int i = get_global_id(0); 
    b[i] = a[i] * 2; 
} 

यह kernel बेहतर लगता है, क्योंकि यह कम वैश्विक स्मृति का उपयोग करता है (एक READ_WRITE है):

__kernel void one_buffer_double(__global float* a) 
{ 
    int i = get_global_id(0); 
    a[i] = a[i] * 2; 
} 

क्या READ_ONLY और WRITE_ONLY झंडे केवल डीबगिंग और त्रुटियों को पकड़ने में मदद के लिए मौजूद हैं?

उत्तर

4

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

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

ध्यान दें कि ओपनक्ल 1.2 के बाद से कुछ अन्य झंडे इस समय से संबंधित हैं कि मेजबान को बफर तक पहुंचने की आवश्यकता है। के होते हैं:

CL_MEM_HOST_NO_ACCESS, 
CL_MEM_HOST_{READ, WRITE}_ONLY, 
CL_MEM_{USE, ALLOC, COPY}_HOST_PTR 

मैं कि इसे फिर से लोगों OpenCL को लागू प्रदर्शन को बढ़ाने के लिए मदद करनी चाहिए अनुमान लगा रहा हूँ, लेकिन मुझे लगता है कि हम कुछ एएमडी या NVIDIA विशेषज्ञों से इनपुट की जरूरत होगी।

कृपया ध्यान दें कि मैंने अभी तक कहा है कि केवल मेरे विचार हैं और किसी भी गंभीर दस्तावेज़ीकरण पर आधारित नहीं हैं (मुझे कोई भी ढूंढने का प्रबंधन नहीं हुआ)।

दूसरी तरफ मैं आपको यह सुनिश्चित करने के लिए कह सकता हूं कि मानक को मजबूर नहीं किया गया है क्योंकि केवल क्विकक्स को निरंतर स्थान में रहने के लिए @Quonux कहा गया है। ऐसा हो सकता है कि कुछ कार्यान्वयन छोटे बफर के लिए ऐसा करते हैं। चलो भूलें कि निरंतर अंतरिक्ष मेमोरी छोटा है ताकि आप फिट करने के लिए केवल इतना बड़ा बफर पढ़ सकें।यह सुनिश्चित करने का एकमात्र तरीका है कि एक बफर निरंतर अंतरिक्ष मेमोरी में है, here समझाया गया है कि आपके कर्नेल कोड में निरंतर कुंजी शब्द का उपयोग करना है। बेशक मेजबान पक्ष में, यदि आप निरंतर बफर का उपयोग करना चाहते हैं तो आपको केवल ध्वज को पढ़ने के लिए उपयोग करना होगा।

4

यह निर्भर करता है,

एक READ_ONLY __global स्मृति स्थान में "ग्लोबल/लगातार मेमोरी डाटा कैश" जो ज्यादा सामान्य कैश या एक GPU पर राम की तुलना में तेजी है संग्रहीत किया जाता है (here देखें), यह एक CPU पर कोई फर्क नहीं पड़ता।

मुझे WRITE_ONLY के किसी भी फायदे नहीं हैं, शायद यह भी मदद करता है क्योंकि GPU जानता है कि यह कैशिंग की आवश्यकता को समझने के लिए डेटा स्ट्रीम कर सकता है।

बस जाओ और उसे मापने के अपने अनिश्चित अगर ...

3

ध्यान दें कि वास्तव में दो प्रकार के हैं। आपके पास CL_MEM_READ_ONLY, CL_MEM_WRITE_ONLY और CL_MEM_READ_WRITE हैं जब आपके बफर आवंटित करते हैं लेकिन फिर आपके पास कर्नेल कोड में अपने पॉइंटर्स को सजाने के लिए __read_only, __write_only और __read_write भी है।

इन दोनों का उपयोग अनुकूलन और त्रुटि जांच दोनों के लिए किया जा सकता है। चलिए पहले प्रदर्शन को देखते हैं। यदि केवल लिखने वाले बफर का सामना करना पड़ता है, तो लिखने के लिए लिखने के लिए अधिक कैश को सहेजने के लिए लिखने की आवश्यकता नहीं होती है (जैसे कैश के माध्यम से लिखना)। यह GPU हार्डवेयर पर बहुत निर्भर करता है और कम से कम NVIDIA हार्डवेयर में वास्तव में इसे लागू करने के लिए आवश्यक निर्देश हैं (.cs और .lu संशोधक)। आप उनके PTX ISA का उल्लेख कर सकते हैं।

st.global.u32 [%r10], %r11; // no cache operation specified 

यह समझ में CUDA तो संकलक उन क्वालिफायर के लिए समकक्ष नहीं है के रूप में करता है:

__kernel void Memset4(__global __write_only unsigned int *p_dest, 
    const unsigned int n_dword_num) 
{ 
    unsigned int i = get_global_id(0); 
    if(i < n_dword_num) 
     p_dest[i] = 0; // this 
} 

के रूप में संकलित हो जाता है: मैं, जैसे वास्तव में इस अनुकूलन प्रदर्शन संकलक का कोई सबूत नहीं देखा है सबसे अधिक संभावना है कि चुपचाप उनको अनदेखा करता है। लेकिन उन्हें वहां रखने में कोई दिक्कत नहीं होती है, हम भविष्य में भाग्यशाली हो सकते हैं। सीयूडीए में, इस कार्यक्षमता में से कुछ को फ़ंक्शन का उपयोग करके और एल 1 (-Xptxas -dlcm=cg) में वैश्विक मेमोरी स्थानांतरण को कैशिंग करने में ऑप्ट इन/आउट करने के लिए कंपाइलर झंडे का उपयोग करके उजागर किया गया है। यदि आप पाते हैं कि कैश को छोड़कर आप एक बड़ा फायदा उठाते हैं तो आप हमेशा asm का उपयोग भी कर सकते हैं।

त्रुटि जांच के लिए, केवल पढ़ने के लिए बफर को लिखना कर्नेल घोषणा में const विनिर्देशक का उपयोग करके आसानी से बचा जाता है। शुद्ध "सी" में केवल लिखने वाले बफर से पढ़ने की अनुमति नहीं है।

मेमोरी होस्ट करने के लिए उन बफरों को मैप करते समय एक और संभावित अनुकूलन होता है। CL_MEM_READ_ONLY बफर मैपिंग करते समय, मैप किए गए क्षेत्र को अनियमित किया जा सकता है क्योंकि होस्ट केवल उस स्मृति को लिखता है, डिवाइस को केवल इसे पढ़ने के लिए। इसी तरह, जब CL_MEM_WRITE_ONLY बफर को अन-मैपिंग करते हैं, तो ड्राइवर को होस्ट मेमोरी से डिवाइस मेमोरी में (होस्ट द्वारा संभावित रूप से संशोधित) की प्रतिलिपि बनाने की आवश्यकता नहीं होती है। मैंने इसे माप नहीं लिया।

एक तरफ ध्यान दें के रूप में, मैं का उपयोग कर की कोशिश की है:

inline unsigned int n_StreamingLoad(__global __read_only const unsigned int *p_src) 
{ 
#ifdef NVIDIA 
    unsigned int n_result; 
    asm("ld.global.cs.u32 %r0, [%r1];" : "=r" (n_result) : "r" (p_src)); 
    return n_result; 
#else // NVIDIA 
    return *p_src; // generic 
#endif // NVIDIA 
} 

inline void StreamingWrite(__global __write_only unsigned int *p_dest, const unsigned int n_value) 
{ 
#ifdef NVIDIA 
    asm("st.global.cs.u32 [%r0], %r1;" : : "r" (p_dest), "r" (n_value) : "memory"); 
#else // NVIDIA 
    *p_dest = n_value; // generic 
#endif // NVIDIA 
} 

जो तुम भी sm_35 उपकरणों के साथ एक सरल memcpy कर्नेल पर लगभग 15 अतिरिक्त जीबी/सेकंड देता है (GTX 780 और K40 पर परीक्षण)। sm_30 पर ध्यान देने योग्य स्पीडअप नहीं देखा है (सुनिश्चित नहीं है कि इसका यहां भी समर्थन किया जाना चाहिए - हालांकि निर्देशों को पीटीएक्स से अलग नहीं किया जा रहा है)। ध्यान दें कि आपको NVIDIA स्वयं को परिभाषित करने की आवश्यकता है (या Detect OpenCL device vendor in kernel code देखें)।

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