【问题标题】:CUBLAS - is matrix-element exponentiation possible?CUBLAS - 矩阵元素求幂可能吗?
【发布时间】:2011-07-23 22:21:18
【问题描述】:

我正在使用 CUBLAS(Cuda Blas 库)进行矩阵运算。

是否可以使用 CUBLAS 来实现矩阵项的求幂/均方根?

我的意思是,拥有 2x2 矩阵

1 4
9 16

我想要的是一个提升到给定值的函数,例如2

1 16
81 256

并计算均方根,例如

1 2
3 4

CUBLAS 可以做到这一点吗?我找不到适合这个目标的函数,但我会先在这里请求开始编写我自己的内核。

【问题讨论】:

  • 注意,这不是矩阵求幂(也不是均方根)。您只是对单个元素执行标量操作。
  • 请原谅错误,是的,我需要执行这样的操作
  • 我已经相应地更新了问题标题。
  • 您只是取示例中每个元素的根,而不是元素的均方根。嗯,实际上单个数字的均方根就是它的绝对值。

标签: matrix cuda cublas


【解决方案1】:

所以这很可能是您必须自己实现的事情,因为库不会为您做这件事。 (可能有一些方法可以根据 BLAS 3 级例程来实现它 - 当然是矩阵元素的平方 - 但它会涉及昂贵且不必要的矩阵向量乘法。我仍然不知道你是怎么做的d 做平方根运算)。原因是这些运算并不是真正的线性代数过程。取每个矩阵元素的平方根并不真正对应于任何基本的线性代数运算。

好消息是这些元素操作在 CUDA 中实现起来非常简单。同样,为了获得最佳性能,可以使用许多调整选项,但可以相当容易地开始。

与矩阵加法运算一样,您将在这里将 NxM 矩阵视为 (N*M) 长度的向量;矩阵的结构对于这些元素操作无关紧要。因此,您将传递一个指向矩阵第一个元素的指针,并将其视为 N*M 数字的单个列表。 (我假设你在这里使用floats,因为你之前在谈论SGEMMSAXPY。)

内核,即实现操作的实际 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() */
}

请注意,如果您对略微增加的误差感到满意,则最大误差为 3 ulp(最后一个单位)的“sqrtf()”函数会明显更快。

如何调用这些内核将取决于您执行操作的顺序。如果您已经对这些矩阵进行了一些 CUBLAS 调用,您将希望在 GPU 内存中已经存在的数组上使用它们。

【讨论】:

  • 非常感谢乔纳森,你写了太多来帮助我。我仍然想知道如何实现一些稍微微妙的细节(块/线程的数量,如何最大化合并,ecc ..),但我会尝试并首先运行一些测试。如果我有任何其他疑问,我会发布另一个问题再次感谢您的帮助!
  • 用户@solvingpuzzles 正确指出,我在上面的代码中拥有的block_id 当然应该是blockIdx.x;我不知道为什么我把block_id 放在那里。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-04-26
  • 2016-05-30
  • 1970-01-01
  • 1970-01-01
  • 2011-07-29
  • 2016-10-10
  • 2015-01-21
相关资源
最近更新 更多