将标量添加到 BLAS (cuBLAS/CUDA) 中的向量

Mat*_*ips 6 c cuda add blas cublas

我不知道我是否只是忽略了一些明显的东西,但尽管进行了适当的谷歌搜索,但我认为无法使用 BLAS 操作简单地向向量(或矩阵)添加标量。我正在尝试在 cuBLAS/CUDA 中执行此操作,因此我将采取任何方式在该框架内完成此操作。BLAS 有<t>scal标量乘法 ( cublas<t>scal) 但加法的模拟在哪里?!即类似于 GSL 的东西gsl_vector_add_constant。我错过了什么?

tal*_*ies 4

完成您所要求的操作的唯一方法可能是应用axpy大小相同的单位向量,并按您要添加的常量进行缩放。

所以操作就变成了X <- X + alpha * I,相当于alpha对 中的每一项进行相加X


编辑:

从评论来看,您似乎预见到为 SAXPY 调用创建单位向量会遇到一些困难。一种方法是使用 memset 调用来设置设备上单位向量的值,如下所示:

#include "cuda.h"
#include "cuda_runtime_api.h"
#include "cublas_v2.h"
#include <iostream>

int main(void)
{

    const int N = 10;
    const size_t sz = sizeof(float) * size_t(N);
    float *A, *I;

    float Ah[N] = { 0., 1., 2., 3., 4., 5., 6., 7., 8., 9. };

    cudaMalloc((void **)&A, sz);
    cudaMemcpy(A, &Ah[0], sz, cudaMemcpyHostToDevice);

    // this creates a bit pattern for a single precision unity value
    // and uses 32-bit memset from the driver API to set the values in the
    // vector.
    const float one = 1.0f;
    const int* one_bits = reinterpret_cast<const int*>(&one);
    cudaMalloc((void **)&I, sz);
    cuMemsetD32(CUdeviceptr(I), *one_bits, N);

    cublasHandle_t h;
    cublasCreate(&h);

    const float alpha = 5.0f;
    cublasSaxpy(h, N, &alpha, I, 1, A, 1);

    cudaMemcpy(&Ah[0], A, sz, cudaMemcpyDeviceToHost);

    for(int i=0; i<N; i++) {
        std::cout << i << " " << Ah[i] << std::endl;
    }

    cublasDestroy(h);
    cudaDeviceReset();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

请注意,这里我直接使用 CUDA 运行时 API 为 CUBLAS 向量分配和复制内存,而不是使用 CUBLAS 辅助函数(无论如何,它们只是围绕运行时 API 调用的非常薄的包装器)。“棘手”的部分是创建一个位模式并使用驱动程序 API memset 函数来设置数组的每个 32 位字。

您同样可以使用推力库中的几行模板代码来完成整个事情,或者只编写自己的内核,这可能很简单

template<typename T>
__global__
void vector_add_constant( T * vector, const T scalar, int N)
{
    int tidx = threadIdx.x + blockIdx.x*blockDim.x;
    int stride = blockDim.x * gridDim.x;

    for(; tidx < N; tidx += stride) {
        vector[tidx] += scalar;
    }
}
Run Code Online (Sandbox Code Playgroud)

[免责声明:该内核是在浏览器中编写的,未经测试。使用风险自担]