क्या आप अंततः चाहते हैं कि क्या आपके ग्रिड और ब्लॉक -1 डी या 2 डी कर रहे हैं अपने इनपुट डेटा एक -1 डी या 2 डी सरणी है इस पर निर्भर करता है, और:
यहाँ कुछ अच्छा स्रोत है। सबसे आसान मामला 1 डी:
shmem[threadIdx.x] = gmem[blockDim.x * blockIdx.x + threadIdx.x];
यह सहसंबंधित है। अंगूठे का नियम मैं उपयोग करता हूं कि ब्लॉक ऑफसेट (ब्लॉकडिम * ब्लॉकआईडीएक्स) के ऑफसेट के रूप में सबसे तेजी से भिन्न समन्वय (थ्रेडआईडीएक्स) जोड़ा जाता है। अंत परिणाम यह है कि ब्लॉक में धागे के बीच इंडेक्सिंग की तरफ 1 है। यदि घुमाव बड़ा हो जाता है, तो आप कोलेसिंग खो देते हैं।
सरल नियम (फर्मि और बाद में जीपीयू पर) यह है कि यदि एक थ्रू में सभी धागे के पते एक ही गठबंधन 128-बाइट रेंज में आते हैं, तो एक मेमोरी लेनदेन परिणाम देगा (माना जाता है कि भार के लिए कैशिंग सक्षम है , जो डिफ़ॉल्ट है)। यदि वे दो गठित 128-बाइट श्रेणियों में आते हैं, तो दो मेमोरी लेनदेन परिणाम इत्यादि।
GT2xx और पहले GPUs पर, यह अधिक जटिल हो जाता है। लेकिन आप प्रोग्रामिंग गाइड में इसका विवरण पा सकते हैं।
अतिरिक्त उदाहरण:
एकत्रित नहीं:
shmem[threadIdx.x] = gmem[blockDim.x + blockIdx.x * threadIdx.x];
एकत्रित नहीं है, लेकिन GT200 पर और बाद में बहुत बुरा नहीं:
stride = 2;
shmem[threadIdx.x] = gmem[blockDim.x * blockIdx.x + stride * threadIdx.x];
नहीं पाए सब पर:
stride = 32;
shmem[threadIdx.x] = gmem[blockDim.x * blockIdx.x + stride * threadIdx.x];
कोआ lesced, 2 डी ग्रिड, 1 डी ब्लॉक:
int elementPitch = blockDim.x * gridDim.x;
shmem[threadIdx.x] = gmem[blockIdx.y * elementPitch +
blockIdx.x * blockDim.x + threadIdx.x];
एकत्रित, 2 डी ग्रिड और ब्लॉक:
int x = blockIdx.x * blockDim.x + threadIdx.x;
int y = blockIdx.y * blockDim.y + threadIdx.y;
int elementPitch = blockDim.x * gridDim.x;
shmem[threadIdx.y * blockDim.x + threadIdx.x] = gmem[y * elementPitch + x];
न तो इनमें से एकत्रित किया जा सकता है, ग्रिड में पहले खंड को छोड़कर। कॉलम प्रमुख क्रम में थ्रेड गिने जाते हैं। – talonmies