मेरे GPU का क्या इंतजार है?


11

मैं अपने AMD Radeon HD 7800 श्रृंखला GPU के साथ उपयोग के लिए एक OpenCL कार्यक्रम लिख रहा हूं। AMD के OpenCL प्रोग्रामिंग गाइड के अनुसार , GPU की इस पीढ़ी की दो हार्डवेयर कतारें हैं जो अतुल्यकालिक रूप से काम कर सकती हैं।

5.5.6 कमांड कतार

दक्षिणी द्वीप समूह और बाद के लिए, उपकरण कम से कम दो हार्डवेयर कंप्यूट कतारों का समर्थन करते हैं। यह एक आवेदन को अतुल्यकालिक सबमिशन और संभवतः निष्पादन के लिए दो कमांड क्यू के साथ छोटे प्रेषण के थ्रूपुट को बढ़ाने की अनुमति देता है। हार्डवेयर गणना कतारों को निम्नलिखित क्रम में चुना जाता है: पहली कतार = यहां तक ​​कि ओसीएल कमांड कतार, दूसरी कतार = विषम ओसीएल कतार।

ऐसा करने के लिए, मैंने GPU को डेटा खिलाने के लिए दो अलग OpenCL कमांड कतारें बनाई हैं। मोटे तौर पर, होस्ट थ्रेड पर चलने वाला प्रोग्राम कुछ इस तरह दिखता है:

static const int kNumQueues = 2;
cl_command_queue default_queue;
cl_command_queue work_queue[kNumQueues];

static const int N = 256;
cl_mem gl_buffers[N];
cl_event finish_events[N];

clEnqueueAcquireGLObjects(default_queue, gl_buffers, N);

int queue_idx = 0;
for (int i = 0; i < N; ++i) {
  cl_command_queue queue = work_queue[queue_idx];

  cl_mem src = clCreateBuffer(CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, ...);

  // Enqueue a few kernels
  cl_mem tmp1 = clCreateBuffer(CL_READ_WRITE);
  clEnqueueNDRangeKernel(kernel1, queue, src, tmp1);

  clEnqueueNDRangeKernel(kernel2, queue, tmp1, tmp1);

  cl_mem tmp2 = clCreateBuffer(CL_READ_WRITE);
  clEnqueueNDRangeKernel(kernel2, queue, tmp1, tmp2);

  clEnqueueNDRangeKernel(kernel3, queue, tmp2, gl_buffer[i], finish_events + i);

  queue_idx = (queue_idx + 1) % kNumQueues;
}

clEnqueueReleaseGLObjects(default_queue, gl_buffers, N);
clWaitForEvents(N, finish_events);

kNumQueues = 1इस एप्लिकेशन के साथ , यह बहुत अधिक काम करता है: यह पूरी तरह से एक ही कमांड कतार में काम करता है जो कि पूरे समय में व्यस्त होने के कारण GPU के साथ पूरा होता है। मैं CodeXL प्रोफाइलर के आउटपुट को देखकर इसे देख सकता हूं:

यहाँ छवि विवरण दर्ज करें

हालांकि, जब मैं सेट करता हूं, तो मैं kNumQueues = 2एक ही बात होने की उम्मीद करता हूं लेकिन काम के साथ समान रूप से दो कतारों में विभाजित हो जाता है। यदि कुछ भी हो, तो मुझे उम्मीद है कि प्रत्येक कतार में एक कतार के समान व्यक्तिगत रूप से एक ही विशेषता होगी: कि यह क्रमिक रूप से तब तक काम करना शुरू करता है जब तक कि सब कुछ नहीं हो जाता। हालांकि, दो कतारों का उपयोग करते समय, मैं देख सकता हूं कि सभी कार्य दो हार्डवेयर कतारों में विभाजित नहीं हैं:

यहाँ छवि विवरण दर्ज करें

GPU के काम की शुरुआत में, कतारें कुछ गुठली को अतुल्य रूप से चलाने का प्रबंधन करती हैं, हालांकि ऐसा लगता है कि न तो कभी पूरी तरह से हार्डवेयर कतारों पर कब्जा होता है (जब तक कि मेरी समझ गलत नहीं है)। GPU के काम के अंत के पास, ऐसा लगता है कि कतारें अनुक्रमिक रूप से केवल एक हार्डवेयर कतार में काम कर रही हैं, लेकिन कई बार ऐसा भी होता है कि कोई गुठली नहीं चल रही है। क्या देता है? क्या मुझे कुछ बुनियादी गलतफहमी है कि रनटाइम को कैसे माना जाता है?

मेरे पास कुछ सिद्धांत हैं कि ऐसा क्यों हो रहा है:

  1. इंटरसेप्टर clCreateBufferकॉल जीपीयू को एक साझा मेमोरी पूल से डिवाइस संसाधनों को समकालिक रूप से आवंटित करने के लिए मजबूर कर रही है जो व्यक्तिगत कर्नेल के निष्पादन को रोकती है।

  2. अंतर्निहित ओपनसीएल कार्यान्वयन भौतिक कतारों के लिए तार्किक कतारों को मैप नहीं करता है, और केवल यह तय करता है कि रनटाइम पर वस्तुओं को कहां रखा जाए।

  3. क्योंकि मैं GL ऑब्जेक्ट्स का उपयोग कर रहा हूं, इसलिए GPU को लिखने के दौरान विशेष रूप से आवंटित मेमोरी तक पहुंच को सिंक्रनाइज़ करने की आवश्यकता होती है।

क्या इनमें से कोई भी धारणा सत्य है? क्या किसी को पता है कि दो-कतार परिदृश्य में प्रतीक्षा करने के लिए GPU क्या हो सकता है? किसी भी और सभी अंतर्दृष्टि की सराहना की जाएगी!


मुझे नहीं पता कि यह कहां कह सकता है कि प्रोग्रामिंग गाइड में दो हार्डवेयर कतारें हैं। क्या आप दस्तावेज़ से एक उद्धरण पोस्ट कर सकते हैं? उल्लेख करें कि कौन सा अध्याय कहता है कि दो कतारें हैं? OpenCL का उपयोग करके रनटाइम में हार्डवेयर कतारों की संख्या क्या है?
एंड्रियास

मैंने अपनी पोस्ट अपडेट कर दी है। यह संभव निष्पादन कहता है , लेकिन अगर यह कुछ कर सकता है तो यह उन सभी को क्यों नहीं कर सकता है? इसके अलावा OpenCL रनटाइम में हार्डवेयर कतार की कोई धारणा नहीं है, इसलिए यह ऐसा कुछ नहीं है जिसे आप क्वेरी कर सकते हैं।
मोकोशा

जवाबों:


2

सामान्य रूप से गणना कतारों का मतलब यह नहीं है कि अब आप समानांतर में 2x प्रेषण कर सकते हैं। एक एकल कतार जो पूरी तरह से गणना इकाइयों को संतृप्त करती है उसके पास बेहतर थ्रूपुट होगा। एकाधिक कतारें उपयोगी होती हैं यदि एक कतार कम संसाधनों (साझा मेमोरी या रजिस्टरों) का उपभोग करती है, तो माध्यमिक कतारें फिर उसी गणना इकाई पर ओवरलैप कर सकती हैं।

रियल-टाइम रेंडरिंग के लिए यह विशेष रूप से छाया रेंडरिंग जैसी चीजों के मामले में होता है जो कि कंप्यूट / शेड्स पर बहुत हल्के होते हैं लेकिन फिक्स्ड फंक्शन हार्डवेयर पर भारी होते हैं, इस प्रकार सेकेंडरी कतार async को चलाने के लिए GPU अनुसूचक को मुक्त कर देते हैं।

रिलीज नोट्स में भी यह पाया गया। अगर यह एक ही मुद्दा है पता नहीं है, लेकिन हो सकता है कि CodeXL महान नहीं है। मैं उम्मीद करूंगा कि इसके पास सबसे अच्छा इंस्ट्रूमेंटेशन नहीं हो सकता है जिसके लिए प्रेषण उड़ान में हैं।

https://developer.amd.com/wordpress/media/2013/02/AMD_CodeXL_Release_Notes.pdf

एक ऐसे अनुप्रयोग के लिए जो एक साथ अतुल्यकालिक डेटा ट्रांसफर और कर्नेल निष्पादन करता है, एप्लिकेशन ट्रेस सत्र दृश्य में दिखाई गई समयरेखा इन कार्यों को ओवरलैप किए जाने पर नहीं दिखाएगी। ऐसा इसलिए है क्योंकि ड्राइवर और हार्डवेयर इन ऑपरेशनों को प्रोफाइलिंग करते समय सिंक्रोनस होने के लिए मजबूर करते हैं। (333,981)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.