Сначала комментарий о
// load center part to shared memory
shmem[threadIdx.x+1] = temp;
Я бы назвал это сохранением в общей памяти ...
Кроме того, несколько идей:
Используйте первый и последний поток в блоке, чтобы вычислять только b(A(in))
Конечно, вам нужно учитывать это при расчете x
(const int x = threadIdx.x + blockIdx.x * (blockDim.x-2);
) и вызывать ваше ядро с большим количеством потоков./blocks.
При выполнении команды C()
у вас будет по два потока на каждый простаивающий блок.Но это не должно иметь большого влияния.
Вот ядро.Это легче понять, если попытаться визуализировать последовательность вычислений.
__global__ void CbA(float *d_in, float *d_out)
{
const int x = threadIdx.x + blockIdx.x * (blockDim.x - 2);
if (x >= N) return;
int x_left = max(x-1, 0); int x_right = min(x+1, N-1);
float temp = b( d_in[x_left] + d_in[x] + d_in[x_right] );
__shared__ float shmem[BLOCK_SIZE]; // = 256
shmem[threadIdx.x] = temp;
__syncthreads();
if (threadIdx.x > 0 && threadIdx.x < blockDim.x-1)
d_out[x-1] = shmem[threadIdx.x-1] + d_in[threadIdx.x] + d_in[threadIdx.x+1];
}
Пусть один поток в блоке также выполняет b(A())
для "граничных частей" блока
Но тогда вы будете использовать только 1 из 32 потоков для этого расчета для каждого блока.Наихудшим случаем будет отношение 1/32 для всего SM на время дополнительных вычислений.
...
// but how to load boundary parts from temp to shmem?
if (threadIdx.x == 0)
{
{
const int x = 0 + blockIdx.x * blockDim.x;
int x_left = max(x-1, 0); int x_right = min(x+1, N-1);
float temp = b( d_in[x_left] + d_in[x] + d_in[x_right] );
shmem[0] = temp;
}
{
const int x = blockDim.x-1 + blockIdx.x * blockDim.x;
int x_left = max(x-1, 0); int x_right = min(x+1, N-1);
float temp = b( d_in[x_left] + d_in[x] + d_in[x_right] );
shmem[blockDim.x-1] = temp;
}
}
// perform function C()
...
Избегайте использования общей памяти
(по крайней мере, в вашем упрощенном примере) Значение temp
является результатом очень простого вычисления.Возможно, лучше всего рассчитать все значения, которые вам нужно выполнить C()
в потоке локально в этом потоке.
__global__ void CbA(float *d_in, float *d_out)
{
const int x = threadIdx.x + blockIdx.x * blockDim.x;
if (x >= N) return;
float temp[3];
for (int i(0); i < 3; ++i)
{
int x_left = max(x-1-1+i, 0); int x_right = min(x+1-1+i, N-1);
temp[i] = b( d_in[x_left] + d_in[x-1+i] + d_in[x_right] );
}
// perform function C()
...
}