У меня есть следующая функция ядра opencl, чтобы получить сумму столбца изображения.ускорение при использовании float4, opencl
__kernel void columnSum(__global float* src,__global float* dst,int srcCols,
int srcRows,int srcStep,int dstStep)
{
const int x = get_global_id(0);
srcStep >>= 2;
dstStep >>= 2;
if (x < srcCols)
{
int srcIdx = x ;
int dstIdx = x ;
float sum = 0;
for (int y = 0; y < srcRows; ++y)
{
sum += src[srcIdx];
dst[dstIdx] = sum;
srcIdx += srcStep;
dstIdx += dstStep;
}
}
}
поручает, что каждый процесс нити столбца здесь, так что много нитей может получить column_sum каждой колонки параллельно.
Я также использую float4, чтобы переписать указанное выше ядро, чтобы каждый поток мог считывать 4 элемента в строке за один раз из исходного изображения, что показано ниже.
__kernel void columnSum(__global float* src,__global float* dst,int srcCols,
int srcRows,int srcStep,int dstStep)
{
const int x = get_global_id(0);
srcStep >>= 2;
dstStep >>= 2;
if (x < srcCols/4)
{
int srcIdx = x ;
int dstIdx = x ;
float4 sum = (float4)(0.0f, 0.0f, 0.0f, 0.0f);
for (int y = 0; y < srcRows; ++y)
{
float4 temp2;
temp2 = vload4(0, &src[4 * srcIdx]);
sum = sum + temp2;
vstore4(sum, 0, &dst[4 * dstIdx]);
srcIdx += (srcStep/4);
dstIdx += (dstStep/4);
}
}
}
В этом случае, теоретически, я считаю, что время, затрачиваемое на втором ядре, чтобы обработать изображение должно быть 1/4 от времени, потребляемого первой функцией ядра. Однако, независимо от того, насколько велико изображение, два ядра почти потребляют одно и то же время. Я не знаю почему. Можете ли вы, ребята, дать мне несколько идей? T
Тогда узким местом является не часть обмена информацией. Является ли производительность приемлемой, кроме того, что вы не получаете 1/4 ускорения? Я прошу, чтобы у вас была проблема с синхронизацией. Сколько вычислений вы выполняете? Простое суммирование - всего лишь пример? –
Вы знаете о инструкциях SIMD, не так ли? Они могут выполнять одну и ту же операцию по значениям 2, 4, 8 или 16 (или больше, в зависимости от аппаратных) одновременно. Возможно, поэтому время одинаковое, потому что он эффективно выполняет ту же работу, но использует инструкции SIMD. Это очень распространено в графических процессорах, но также может наблюдаться на процессорах в меньшей степени. 4 поплавка хороша для регистра SSE, звучит правильно. Это, и вы можете просто быть узким местом в передаче памяти, как отмечает Csaba. – Thomas
Ну, причина, по которой я использую float4, выглядит так: если у нас есть 256 потоков, которые могут работать одновременно. У нас есть изображение 1024 * 1024. Если мы используем первое ядро, 256 потоков сначала обрабатывают первые 256 столбцов, затем обрабатывают следующие 256 столбцов и так далее, пока весь столбец не будет завершен. В этом случае будет потребляться 4 * t, где t обозначает время, затрачиваемое 256 потоками для обработки 256 столбцов. Однако, если мы используем второе ядро, поскольку каждый поток обрабатывает 4 элемента в строке изображения, 256 потоков могут обрабатывать 1024 столбца с временем t.Это просто оценка. @Thomas – user2326258