الدرس 27: ضرب المصفوفات باستخدام البلاطات (Tiled)
ضرب المصفوفات C = A * B يحسب كل عنصر C[row][col] بوصفه مجموعًا لحواصل الضرب على امتداد البُعد K: C[row][col] = المجموع على k لـ A[row][k] * B[k][col]. في النسخة الساذجة، كل thread مسؤول عن عنصر واحد من C يقرأ صفًّا كاملًا من A وعمودًا كاملًا من B مباشرةً من الذاكرة العامة — وهي الطبقة الأبطأ. المشكل
تخيّل أنك تُعِدّ طبقًا وتركض مرارًا إلى المستودع البعيد لإحضار المكوّنات نفسها بالضبط. بدلًا من ذلك، تُحضِر صندوقًا كاملًا مرة واحدة إلى طاولة المطبخ (الرفّ القريب)، ويسحب منه جميع الطهاة بسرعة. هذا هو tiling تمامًا: تُحضِر بلاطة من البيانات مرة واحدة إلى shared memory القريبة، وتعيد استخدامها هناك مرارًا وتكرارًا.
- ضرب المصفوفات المبلَّط
- خوارزمية ضرب مصفوفات تُحمّل بلاطات من A وB إلى shared memory، وتُزامن، وتراكم من هناك — موفّرةً قراءات من الذاكرة العامة.
- بلاطة (tile)
- كتلة فرعية بحجم TILE x TILE من المصفوفة، تُحمَّل دفعةً واحدة إلى shared memory ويستخدمها جميع threads في الـ block.
- إعادة الاستخدام في shared memory
- كل عنصر مُحمَّل إلى shared memory يُقرأ بواسطة TILE من threads المختلفة، فتخدم قراءة عامة واحدة حواصل ضرب كثيرة.
- البُعد K
- البُعد المشترك في حاصل الضرب: A هي M x K وB هي K x N. المجموع على k يمتدّ على امتداد K ويُحسب بلاطةً بلاطةً.