CUBLAS - возможно ли возведение в степень матричных элементов?

Я использую CUBLAS (библиотеки Cuda Blas) для матричных операций.

Можно ли использовать CUBLAS для достижения возведения в степень / среднеквадратичного значения элементов матрицы?

Я имею в виду, имея матрицу 2x2

1 4
9 16

Я хочу, чтобы функция повышалась до заданного значения, например. 2

1 16
81 256

и вычисление среднеквадратичного значения, например

1 2
3 4

Возможно ли это с CUBLAS? Я не могу найти функцию, подходящую для этой цели, но сначала я попрошу здесь начать кодирование собственного ядра.


person Marco A.    schedule 27.03.2011    source источник
comment
Обратите внимание, это не матричное возведение в степень (и не среднеквадратичное значение). Вы просто выполняете скалярные операции над отдельными элементами.   -  person Oliver Charlesworth    schedule 27.03.2011
comment
Извините за ошибку, да мне нужно проделать такие операции   -  person Marco A.    schedule 27.03.2011
comment
Я соответствующим образом обновил заголовок вопроса.   -  person Jonathan Dursi    schedule 27.03.2011
comment
Вы просто берете корень каждого элемента в своем примере, который не является среднеквадратическим значением ваших элементов. На самом деле среднеквадратичное значение одного числа - это просто его абсолютное значение.   -  person Christian Rau    schedule 26.10.2012


Ответы (1)


Так что это вполне может быть что-то, что вам нужно реализовать самостоятельно, потому что библиотека не сделает этого за вас. (Вероятно, есть какой-то способ реализовать некоторые из них в терминах процедур уровня 3 BLAS - конечно, возведение элементов матрицы в квадрат - но это потребует дорогостоящих и ненужных в других отношениях умножений матрицы на вектор. И я до сих пор не знаю, как вы » d выполнить операцию квадратного корня). Причина в том, что эти операции на самом деле не являются процедурами линейной алгебры; извлечение квадратного корня из каждого матричного элемента на самом деле не соответствует какой-либо фундаментальной операции линейной алгебры.

Хорошая новость в том, что эти поэлементные операции очень просто реализовать в CUDA. Опять же, есть много вариантов настройки, с которыми можно поиграть для лучшей производительности, но начать можно довольно легко.

Как и в случае с операциями сложения матриц, здесь вы будете обрабатывать матрицы NxM как векторы длины (N * M); структура матрицы не имеет значения для этих поэлементных операций. Таким образом, вы передадите указатель на первый элемент матрицы и будете рассматривать его как единый список из N * M чисел. (Я предполагаю, что вы здесь используете floats, как вы говорили о SGEMM и SAXPY ранее.)

Ядро, фактический бит кода CUDA, который реализует операцию, довольно прост. На данный момент каждый поток будет вычислять квадрат (или квадратный корень) одного элемента массива. (Оптимально это или нет для производительности - это то, что вы можете проверить). Итак, ядра будут выглядеть следующим образом. Я предполагаю, что вы делаете что-то вроде B_ij = (A_ij) ^ 2; если вы хотите выполнить операцию на месте, например, A_ij = (A_ij) ^ 2, вы тоже можете это сделать:

__global__ void squareElements(float *a, float *b, int N) {
    /* which element does this compute? */
    int tid = blockDim.x * blockIdx.x + threadIdx.x;

    /* if valid, squre the array element */
    if (tid < N) 
            b[tid] = (a[tid]*a[tid]);
}

__global__ void sqrtElements(float *a, float *b, int N) {
    /* which element does this compute? */
    int tid = blockDim.x * blockIdx.x + threadIdx.x;

    /* if valid, sqrt the array element */
    if (tid < N) 
            b[tid] = sqrt(a[tid]);   /* or sqrtf() */
}

Обратите внимание: если у вас все в порядке с незначительно увеличенной ошибкой, функция sqrtf () с максимальной ошибкой 3 ulp (единицы на последнем месте) будет значительно быстрее.

Как вы назовете эти ядра, будет зависеть от порядка, в котором вы делаете что-то. Если вы уже сделали несколько вызовов CUBLAS для этих матриц, вы захотите использовать их в массивах, которые уже находятся в памяти GPU.

person Jonathan Dursi    schedule 27.03.2011
comment
Большое спасибо, Джонатан, ты написал слишком много, чтобы помочь мне. Мне все еще интересно, как реализовать некоторые слегка тонкие детали (количество блоков / потоков, как максимизировать слияние и т. Д.), Но я попробую и сначала проведу несколько тестов. Я отправлю еще один вопрос, если у меня возникнут другие сомнения. Еще раз спасибо за вашу помощь! - person Marco A.; 27.03.2011
comment
Пользователь @solvingpuzzles прямо указал, что block_id, которое у меня было в приведенном выше коде, конечно же, должно быть blockIdx.x; Понятия не имею, зачем я туда положил block_id. - person Jonathan Dursi; 26.10.2012