На этом шаге мы рассмотрим эффективное использование разделяемой памяти.
При работе с разделяемой памятью есть свои паттерны оптимального доступа к ней, обеспечивающее наибольшую скорость доступа.
Для повышения пропускной способности вся разделяемая память разбита на 16 банков, каждый из них способен выполнить одно чтение или запись 32-битового слова. Таким образом, если все 16 нитей полу-warp'a обращаются к 16 32-битовым словам, лежащим в разных банках, то мы получим результат без дополнительных задержек.
Если же в один банк придет сразу несколько обращений, то он должен будет выполнить их последовательно, одно за другим. Такая ситуация называется конфликтом банков и характеризуется порядком конфликта - максимальным числом обращений в один банк.
Таким образом, если у нас имеет место конфликт второго порядка даже для одного банка, то скорость доступа к разделяемой памяти в этом случае снижается вдвое. Поскольку обращение к разделяемой памяти происходит отдельно для каждого полу-warp'a, то нам необходимо отслеживать лишь конфликты банков в пределах каждого полу-warp'a. разбиение всей разделяемой памяти по банкам организовано следующим образом: подряд идущие 32-битовые слова попадают в подряд идущие банки. Таким образом, если 16 нитей полу-warp'a обращаются к 16 подряд идущим 32-битовым словам, то никакого конфликта банков не возникает - в этом и смысл такого разбиения на банки.
На рисунке 1 приведены типичные паттерны доступа к разделяемой памяти, не приводящие к появлению конфликта банков.
Рис. 1. Разбиение разделяемой памяти на банки
Так же возможен еще один вариант бесконфликтного доступа к разделяемой памяти - это когда все 16 нитей обращаются к одному и тому же адресу (так называемому broadcast).
На следующем шаге мы рассмотрим глобальную память.