Объединение памяти при внедрении уравнений FDTD

60
4

Я пытался реализовать уравнения FDTD на графическом процессоре. Сначала я реализовал ядро, которое использовало глобальную память. Объединение памяти было не так уж велико. Поэтому я реализовал другое ядро, которое использовало разделяемую память для загрузки значений. Я работаю над сеткой 1024x1024.

Код ниже

__global__ void update_Hx(float *Hx, float *Ez, float *coef1, float* coef2){
int x = threadIdx.x + blockIdx.x * blockDim.x;
int y = threadIdx.y + blockIdx.y * blockDim.y;
int offset = x + y * blockDim.x * gridDim.x;
__shared__ float Ez_shared[BLOCKSIZE_HX][BLOCKSIZE_HY + 1];
/*int top = offset + x_index_dim;*/
if(threadIdx.y == (blockDim.y - 1)){
Ez_shared[threadIdx.x][threadIdx.y] = Ez[offset];
Ez_shared[threadIdx.x][threadIdx.y + 1] = Ez[offset + x_index_dim];
}
else{
Ez_shared[threadIdx.x][threadIdx.y] = Ez[offset];
}
}

Константы BLOCKSIZE_HX= 16 и BLOCKSIZE_HY= 16.

Когда я запускаю визуальный профайлер, он все еще говорит, что память не объединена.

EDIT: Я использую графическую карту GT 520 с вычислительной способностью cuda 2.1. Мои глобальные транзакции L2/Access = 7.5 т.е. есть 245 760 транзакций L2 для 32768 исполнений строки Ez_shared[threadIdx.x][threadIdx.y] = Ez[offset];

Global memory load efficiency составляет 50%.

Global memory load efficiency= 100 * gld_requested_throughput/gld_throughput

Я не могу понять, почему так много обращений к памяти, хотя мои потоки ищут 16 последовательных значений. Может ли кто-нибудь указать мне, что я делаю неправильно?

EDIT: Спасибо за помощь.

спросил(а) 2013-02-11T14:01:00+04:00 8 лет назад
1
Решение
60

Здесь проблема с шаблоном доступа к памяти. Вы получаете только 50% эффективности (как для L1, так и для L2), потому что вы получаете доступ к последовательным регионам из 16 поплавков, то есть 64 байта, но размер транзакции L1 составляет 128 байт. Это означает, что для каждых 64 байтов 128 байтов должны быть загружены в L1 (и, следовательно, также в L2).

У вас также есть проблемы с конфликтами в банках с разделяемой памятью, но это в настоящее время не отрицательно влияет на эффективность глобальной загрузки памяти.

Вы можете решить проблему эффективности загрузки несколькими способами. Проще всего было бы изменить размер блока размера x на 32. Если это не вариант, вы можете изменить расположение данных глобальной памяти, чтобы каждый два последовательных блока blockIdx.y([0, 1], [2,3] и т.д. ) будут отображены в непрерывный блок памяти. Если даже это не вариант, и вы должны загружать глобальные данные только один раз, вы могли бы использовать не кэшированные нагрузки глобальной памяти для обхода L1 - это поможет, потому что L2 использует транзакции по 32 байта, поэтому ваши 64 байта будут загружены в два L2 транзакции без накладных расходов.

ответил(а) 2013-02-12T13:59:00+04:00 8 лет назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема