Проблема в функции ядра OpenCL
Я новичок в Open-cl и пытаюсь написать код ядра для следующей операции матрицы:
A is a 2X2 matrix:
A = [1 2] ----> row1
[3 4] ----->row2
I need to compute:
1) s1 = transpose(row1) X row1
2) s1 = transpose(row2) X row2
3) Sum = s1+s2
Я написал код ядра для уровня строки (т.е. я могу сделать транспонирование (row1) X row1) - это служит цели только для первой строки
Как использовать параллелизм, чтобы вычислить это для каждой строки и найти окончательную сумму в функции ядра?
private static String programSource1 =
"__kernel"+
" void matrixMul(__global float* A, __global float* C, int rowLength)"+
"{"+
"int row = get_global_id(1);"+
"int col = get_global_id(0);"+
"C[row*rowLength+col] = A[col] * A[row];"+
"}";
1 ответ
#define MAX_ROW_LENGTH 2 // or more
__kernel void matrixMul(__global float* A, __global float* C,
int rowLength)
{
__local float buffer[MAX_ROW_LENGTH * MAX_ROW_LENGTH];
__local float s1[MAX_ROW_LENGTH * MAX_ROW_LENGTH];
int col = get_global_id(0);
int row = get_global_id(1);
int rows = get_global_size(1);
// read the matrix from global to local memory
buffer[row * rowLength + col] = A[row * rowLength + col];
s1[row * rowLength + col] = 0.0f;
barrier(CLK_LOCAL_MEM_FENCE);
for (int i = 0; i < rows; ++i)
{
s1[row * rowLength + col] +=
buffer[i * rowLength + col] * buffer[i * rowLength + row];
}
C[row * rowLength + col] = s1[row*rowLength+col];
}
Вот код ядра, который делает то, что вы хотите для маленьких матриц. Ядро использует локальную память для уменьшения доступа к глобальной памяти. Для таких небольших задач (матрица 2x2) это позволяет достичь чего угодно, но если вы вычисляете большие матрицы, это может немного ускорить процесс. Тем не менее, это короткий пример и не оптимизирован. Он имеет некоторые ограничения:
- этот код поддерживает только локальные размеры рабочей группы, равные глобальному размеру рабочей группы (без кусков)
- если ваши матрицы станут большими, общая память ограничит использование вашего графического процессора и
- если ваши матрицы станут действительно большими, их не хватит общей памяти
Если вы не хотите, чтобы локальная память удалялась, замените вызовы буфера внутри цикла for на A и запишите непосредственно в C вместо s1.