【问题标题】:Using Cuda for non-square matrix multiplication使用 Cuda 进行非方阵乘法
【发布时间】:2017-01-08 21:51:01
【问题描述】:

我最近几天开始使用 cuda。编写一个将两个大小为 N x N 的矩阵相乘的程序是没有问题的。在内核函数中我使用了这段代码:

    for(int i = 0; i < width; i++){
        sum += a[row * width + i] * b[i * width + col];
        c[row * width + col] = sum;
    }

如何设计核函数以将大小为 1 x N 的矩阵与大小为 N x M 的矩阵相乘

【问题讨论】:

  • a matrix of the size N - 你的意思是 N x N 吗?
  • 我不明白这里的问题。您显示的代码只是行和列的内积(为什么存储在循环内?),无论涉及的矩阵的其他维度如何,都不会改变。
  • 不,我想将 1 维矩阵 N 与 2 维矩阵 N x M 相乘。我存储结果的矩阵必须是 M 大。 @talonmies,我没有更改上面的代码。它可以很好地将两个大小为 N x N 的矩阵相乘。但是对于非方阵,尽管我在“a 索引”中使用了高度参数,但它并没有。
  • 最简单的方法是填充正方形类型并在内核中添加范围检查以避免不必要的计算
  • 将 1xN 矩阵乘以 NxM 矩阵以产生 1xM 矩阵通常称为矩阵向量乘法。如果您对性能感兴趣,请使用 cublas。如果您想编写自己的代码,正如@talonmies 已经指出的那样,像您展示的那样的矩阵矩阵乘法内核应该可以工作。如果您无法使其工作并需要帮助,您可能应该在此问题中提供minimal reproducible example(不是在外部链接中)。它应该是一个完整的代码,而不仅仅是一个内核。

标签: c matrix cuda


【解决方案1】:

我现在已经找到了解决这个问题的方法:

    #include <stdio.h>
#include <iostream>

using namespace std;

__global__
void kernel(float *a, float *b, float *c, int N, int M) {
    int tid = threadIdx.x + blockIdx.x * blockDim.x;
    float sum = 0;
    if (tid < M) {
        for (int i = 0; i < N; i++)
            sum += a[i] * b[(i * M) + tid];
        c[tid] = sum;

    }
}

int main(void) {

    float *dev_a, *dev_b, *dev_c;

    int N = 16;
    int M = 12;

    float a[N];
    float b[N][M];
    float c[M];

    for (int i = 0; i < N; i++) {
        a[i] = 1.0;
    }

    for (int i = 0; i < N; i++) {
        for (int e = 0; e < M; e++) {
            b[i][e] = 1.0;
        }
    }

    cudaMalloc((void**) &dev_a, sizeof(float) * N);
    cudaMalloc((void**) &dev_b, sizeof(float) * N * M);
    cudaMalloc((void**) &dev_c, sizeof(float) * M);

    cudaMemcpy(dev_a, a, sizeof(float) * N, cudaMemcpyHostToDevice);
    cudaMemcpy(dev_b, b, sizeof(float) * N * M, cudaMemcpyHostToDevice);

    kernel<<<M / 256 + 1, 256>>>(dev_a, dev_b, dev_c, N, M);

    cudaMemcpy(c, dev_c, sizeof(float) * M, cudaMemcpyDeviceToHost);

    cudaFree(dev_a);
    cudaFree(dev_b);
    cudaFree(dev_c);

    for (int i = 0; i < M; i++) {
        cout << c[i] << endl;
    }

    return 0;
}

但我还有一个问题。出于性能原因,将内核中的 for 循环操作拆分为多个内核是否有意义?

【讨论】:

    猜你喜欢
    • 2011-07-24
    • 2013-09-30
    • 2012-03-04
    • 2013-12-11
    • 2012-05-01
    • 1970-01-01
    • 2015-03-09
    • 1970-01-01
    • 2012-05-06
    相关资源
    最近更新 更多