فهم أبعاد شبكة CUDA ، وأبعاد كتلة وتنظيم المواضيع (شرح بسيط) [مغلق

StackOverflow https://stackoverflow.com/questions/2392250

  •  25-09-2019
  •  | 
  •  

سؤال

كيف يتم تنظيم المواضيع لتنفيذها بواسطة وحدة معالجة الرسومات؟

هل كانت مفيدة؟

المحلول

المعدات

إذا كان جهاز GPU يحتوي ، على سبيل المثال ، على 4 وحدات متعددة المعالجة ، ويمكنها تشغيل 768 مؤشرات ترابط لكل منها: ثم في لحظة معينة ، لن يتم تشغيل مؤشرات الترابط أكثر من 4*768 بالتوازي (إذا خططت لمزيد من المواضيع ، فسوف ينتظرون دورهم).

برمجة

يتم تنظيم المواضيع في كتل. يتم تنفيذ كتلة من قبل وحدة المعالجة المتعددة. يمكن تعريف مؤشرات ترابط الكتلة (مفهرسة) باستخدام 1Dimension (x) ، 2dimensions (x ، y) أو 3DIM (x ، y ، z) ولكن على أي حال xذz <= 768 لمثالنا (تنطبق القيود الأخرى على x ، y ، z ، راجع الدليل وقدرة جهازك).

من الواضح ، إذا كنت بحاجة إلى أكثر من هذه الخيوط 4*768 ، فأنت بحاجة إلى أكثر من 4 كتل. يمكن أيضًا فهرسة الكتل 1D أو 2D أو 3D. هناك قائمة انتظار من الكتل التي تنتظر الدخول إلى وحدة معالجة الرسومات (لأنه ، في مثالنا ، يحتوي وحدة معالجة الرسومات على 4 معالجات متعددة ، ويتم تنفيذ 4 كتل فقط في وقت واحد).

الآن حالة بسيطة: معالجة صورة 512x512

لنفترض أننا نريد أن يعالج موضوع واحد بكسل واحد (I ، J).

يمكننا استخدام كتل من 64 موضوع لكل منهما. ثم نحتاج إلى 512*512/64 = 4096 كتل (حتى يكون لديك 512 × 512 موضوع = 4096*64)

من الشائع تنظيم (لجعل فهرسة الصورة أسهل) الخيوط في كتل ثنائية الأبعاد تحتوي على blockdim = 8 × 8 (64 مؤشرات ترابط لكل كتلة). أنا أفضل أن أسميها threadsperblock.

dim3 threadsPerBlock(8, 8);  // 64 threads

و 2D Griddim = 64 × 64 كتل (كتل 4096 مطلوبة). أنا أفضل أن أسميها numblocks.

dim3 numBlocks(imageWidth/threadsPerBlock.x,  /* for instance 512/8 = 64*/
              imageHeight/threadsPerBlock.y); 

تم إطلاق kernel مثل هذا:

myKernel <<<numBlocks,threadsPerBlock>>>( /* params for the kernel function */ );       

أخيرًا: سيكون هناك شيء مثل "قائمة انتظار من 4096 كتل" ، حيث تنتظر كتلة واحدة من المعالجات المتعددة في وحدة معالجة الرسومات لتنفيذ 64 مؤشرات الترابط.

في kernel ، يتم حساب البكسل (i ، j) المراد معالجتها بواسطة مؤشر ترابط بهذه الطريقة:

uint i = (blockIdx.x * blockDim.x) + threadIdx.x;
uint j = (blockIdx.y * blockDim.y) + threadIdx.y;

نصائح أخرى

لنفترض أن وحدة معالجة الرسومات 9800GT: 14 معالجات متعددة ، كل منها لديه 8 معالجات مؤدية ويشعر المعالجات هو 32 مما يعني أن كل معالج ThreadProcessor يعالج ما يصل إلى 32 مؤشر ترابط. 14*8*32 = 3584 هو الحد الأقصى لعدد مؤشرات الترابط Cuncurrent Actuall.

إذا قمت بتنفيذ هذه النواة بأكثر من 3584 مؤشر ترابط (قل 4000 خيوط وليس من المهم كيف تحدد الكتلة والشبكة. سيعاملها GPU مثلها):

func1();
__syncthreads();
func2();
__syncthreads();

ثم ترتيب تنفيذ هاتين الوظيفتين هو كما يلي:

1.func1 يتم تنفيذها لأول 3584 مؤشر ترابط

2.func2 يتم تنفيذها لأول 3584 مؤشر ترابط

3. يتم تنفيذ FUNC1 للخيوط المتبقية

4. يتم تنفيذ Func2 للمواضيع المتبقية

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top