如何像python那样编写cuda c argmax内核,并让它解码一个热矩阵?

如何像python那样编写cuda c argmax内核,并让它解码一个热矩阵?,cuda,Cuda,如标题所示 这是代码 其中show_data()和get_data()是显示和导入数据的函数 我不知道如何通过一个列主要的单键矩阵(可以放入cublas函数)列出,并像python的argmax函数一样对其进行解码 我知道我一定是把argmax内核中的索引搞砸了,不知道如何修复它 数据如下: $ cat t23.cu #include <iostream> #include <cublas_v2.h> #define IDX2C(i,j,ld) (((j)*(ld))+(

如标题所示

这是代码

其中show_data()和get_data()是显示和导入数据的函数

我不知道如何通过一个列主要的单键矩阵(可以放入cublas函数)列出,并像python的argmax函数一样对其进行解码

我知道我一定是把argmax内核中的索引搞砸了,不知道如何修复它

数据如下:

$ cat t23.cu
#include <iostream>
#include <cublas_v2.h>
#define IDX2C(i,j,ld) (((j)*(ld))+(i))


__host__ __device__ void argmax(float *data, float *dataout, int ld, int sd, int start, int inc) {
    for (int i = start; i < ld; i+=inc) {
        float valout = 1.0f;
        float temp = data[IDX2C(i, 0, ld)];
        for (int j = 1; j < sd; j++) {
            float val = data[IDX2C(i, j, ld)];
            if (temp <= val) {
                temp = val;
                valout += 1.0f;
            }
        }
        dataout[i]  = valout;
    }
}

__global__ void argmax_kernel(float *data, float *dataout, int ld, int sd) {
    int stride = gridDim.x * blockDim.x;
    int tid = blockDim.x * blockIdx.x + threadIdx.x;
    argmax(data, dataout, ld, sd, tid, stride);
}

int main() {
    float *y_in, *y_out;
    float *d_yin, *d_yout;
    int rows_y = 20;
    int cols_y = 10;
    int size_y = rows_y*cols_y;
    float d_in[cols_y][rows_y] = {
{1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.},
{0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.},
{0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0.},
{0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.},
{0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.},
{0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.},
{0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0.},
{0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.},
{0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.}};

    y_in = (float*)malloc(size_y * sizeof(float));
    y_out = (float*)malloc(rows_y * sizeof(float));
    //transpose
    for (int r = 0; r < cols_y; r++)
      for (int c = 0; c < rows_y; c++)
        y_in[IDX2C(c,r,rows_y)] = d_in[r][c];
    cudaMalloc((void**)&d_yin, size_y * sizeof(*y_in));
    cudaMalloc((void**)&d_yout, rows_y * sizeof(*y_out));

    cudaMemcpy(d_yin, y_in, size_y * sizeof(float), cudaMemcpyHostToDevice);
    argmax(y_in, y_out, rows_y, cols_y, 0, 1);
    for (int i = 0; i <  rows_y; i++)
      std::cout << y_out[i] << " ";
    std::cout << std::endl;
    dim3 dimBlock(256);
    int threadBlocks = (size_y + (dimBlock.x - 1)) / dimBlock.x;
    if (threadBlocks > 65520) threadBlocks = 65520;
    dim3 dimGrid(threadBlocks);

    argmax_kernel<<<dimGrid, dimBlock>>>(d_yin, d_yout, rows_y, cols_y);
    cudaMemcpy(y_out, d_yout, rows_y*sizeof(*y_out), cudaMemcpyDeviceToHost);
    for (int i = 0; i <  rows_y; i++)
      std::cout << y_out[i] << " ";
    std::cout << std::endl;


    cudaFree(d_yin);
    cudaFree(d_yout);

    free(y_in);
    free(y_out);

}
$ nvcc -o t23 t23.cu
$ cuda-memcheck ./t23
========= CUDA-MEMCHECK
1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10
========= ERROR SUMMARY: 0 errors
[[1.0.0.0.0.0.0.0.0.0.1.0.0.0.0.0.0.0.0]

[0.1.0.0.0.0.0.0.0.0.0.1.0.0.0.0.0.0.0]

[0.0.1.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0.0.0]

[0.0.0.1.0.0.0.0.0.0.0.0.0.1.0.0.0.0.0.0]

[0.0.0.0.1.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0.0]

[0.0.0.0.0.1.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0]

[0.0.0.0.0.1.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0]

[0.0.0.0.0.0.0.1.0.0.0.0.0.0.0.0.0.0.1.0.0]

[0.0.0.0.0.0.0.0.1.0.0.0.0.0.0.0.0.0.0.1.0]

[0.0.0.0.0.0.0.0.1.0.0.0.0.0.0.0.0.0.1.]]

输出应如下所示:

[1 2 3 4 5 6 7 8 9 10 1 2 3 4 6 7 8 9 10]

#define IDX2C(i,j,ld) (((j)*(ld))+(i))

__global__ void argmax_kernel(float *data, float *dataout, int ld, int sd) {
    int stride = gridDim.x * blockDim.x;
    int tid = blockDim.x * blockIdx.x + threadIdx.x;
    float temp = 0.0f;

    int i = 0;
    int j = 0;


    for (i = 0; i < ld; i++) {
        for (j = (tid + i*sd*stride); j < sd; j+= stride) {
            if (j = (tid + i*sd*stride)) {
                temp = data[j];
                dataout[i*sd*stride] = 1.0f;
            }
            else if (temp <= data[j]) {
                temp = data[j];
                dataout[i*sd*stride] += 1.0f;
            }
        }
    }
}

void argmax(float *data, float *dataout, int ld, int sd) {
    int i = 0;
    int j = 0;
    float temp = 0.0f;

    for (i = 0; i < ld; i++) {
        for (j = 0; j < sd; j++) {
            if (j == 0) {
                temp = data[IDX2C(i, j, ld)];
                dataout[i] = 1.0f;
            }
            else if (temp <= data[IDX2C(i, j, ld)]) {
                temp = data[IDX2C(i, j, ld)];
                dataout[i] = dataout[i] + 1.0f;
            }
        }
    }
}

int main() {
    float *y_in, *y_out;
    float *d_yin, *d_yout;
    int rols_y = 20;
    int cols_y = 10;
    int size_y = rols_y*cols_y;
    char y_file_name[100] = "argmax.csv";


    y_in = (float*)malloc(size_y * sizeof(float));
    y_out = (float*)malloc(rols_y * sizeof(float));

    cudaMalloc((void**)&d_yin, size_y * sizeof(*y_in));
    cudaMalloc((void**)&d_yout, rols_y * sizeof(*y_out));

    get_ydata(y_in, y_file_name);
    show_data(y_in, rols_y, cols_y);

    cudaMemcpy(d_yin, y_in, size_y * sizeof(float), cudaMemcpyHostToDevice);
    argmax(y_in, y_out, rols_y, cols_y);
    show_data(y_out, rols_y, 1);


    dim3 dimBlock(256);
    int threadBlocks = (size_y + (dimBlock.x - 1)) / dimBlock.x;
    if (threadBlocks > 65520) threadBlocks = 65520;
    dim3 dimGrid(threadBlocks);

    argmax_kernel<<<dimGrid, dimBlock>>>(d_yin, d_yout, rols_y, cols_y);


    cudaFree(d_yin);
    cudaFree(d_yout);

    free(y_in);
    free(y_out);

    system("pause");
    return EXIT_SUCCESS;
}
定义IDX2C(i,j,ld)(((j)*(ld))+(i)) __全局无效argmax内核(浮点*数据,浮点*数据输出,整数ld,整数sd){ int stride=gridDim.x*blockDim.x; int tid=blockDim.x*blockIdx.x+threadIdx.x; 浮子温度=0.0f; int i=0; int j=0; 对于(i=0;i否则,如果(temp您的内核代码中存在如下错误:

if (j = (tid + i*sd*stride))
但我无法更全面地解释您的内核代码发生了什么。这些对我来说都没有意义。我认为最简单的方法就是在内核中复制主机代码,只将
ld
中的外部循环转换为网格跨步循环,这似乎是您的愿望。下面是一个示例:

 $ cat t23.cu
#include <iostream>
#include <cublas_v2.h>
#define IDX2C(i,j,ld) (((j)*(ld))+(i))

__global__ void argmax_kernel(float *data, float *dataout, int ld, int sd) {
    int stride = gridDim.x * blockDim.x;
    int tid = blockDim.x * blockIdx.x + threadIdx.x;
    float temp = 0.0f;

    int i = 0;
    int j = 0;


    for (i = tid; i < ld; i+= stride) {
        for (j = 0; j < sd; j++) {
            if (j == 0) {
                temp = data[IDX2C(i,j, ld)];
                dataout[i] = 1.0f;
            }
            else if (temp <= data[IDX2C(i, j, ld)]) {
                temp = data[IDX2C(i, j, ld)];
                dataout[i] += 1.0f;
            }
        }
    }
}

void argmax(float *data, float *dataout, int ld, int sd) {
    int i = 0;
    int j = 0;
    float temp = 0.0f;

    for (i = 0; i < ld; i++) {
        for (j = 0; j < sd; j++) {
            if (j == 0) {
                temp = data[IDX2C(i, j, ld)];
                dataout[i] = 1.0f;
            }
            else if (temp <= data[IDX2C(i, j, ld)]) {
                temp = data[IDX2C(i, j, ld)];
                dataout[i] = dataout[i] + 1.0f;
            }
        }
    }
}

int main() {
    float *y_in, *y_out;
    float *d_yin, *d_yout;
    int rows_y = 20;
    int cols_y = 10;
    int size_y = rows_y*cols_y;
    float d_in[cols_y][rows_y] = {
{1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.},
{0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0.},
{0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0.},
{0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.},
{0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0.},
{0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.},
{0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.},
{0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0.},
{0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.},
{0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.}};

    y_in = (float*)malloc(size_y * sizeof(float));
    y_out = (float*)malloc(rows_y * sizeof(float));
    //transpose
    for (int r = 0; r < cols_y; r++)
      for (int c = 0; c < rows_y; c++)
        y_in[IDX2C(c,r,rows_y)] = d_in[r][c];
    cudaMalloc((void**)&d_yin, size_y * sizeof(*y_in));
    cudaMalloc((void**)&d_yout, rows_y * sizeof(*y_out));

    cudaMemcpy(d_yin, y_in, size_y * sizeof(float), cudaMemcpyHostToDevice);
    argmax(y_in, y_out, rows_y, cols_y);
    for (int i = 0; i <  rows_y; i++)
      std::cout << y_out[i] << " ";
    std::cout << std::endl;
    dim3 dimBlock(256);
    int threadBlocks = (size_y + (dimBlock.x - 1)) / dimBlock.x;
    if (threadBlocks > 65520) threadBlocks = 65520;
    dim3 dimGrid(threadBlocks);

    argmax_kernel<<<dimGrid, dimBlock>>>(d_yin, d_yout, rows_y, cols_y);
    cudaMemcpy(y_out, d_yout, rows_y*sizeof(*y_out), cudaMemcpyDeviceToHost);
    for (int i = 0; i <  rows_y; i++)
      std::cout << y_out[i] << " ";
    std::cout << std::endl;


    cudaFree(d_yin);
    cudaFree(d_yout);

    free(y_in);
    free(y_out);

}
$ nvcc -o t23 t23.cu
$ cuda-memcheck ./t23
========= CUDA-MEMCHECK
1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10
========= ERROR SUMMARY: 0 errors
$

对于其他读者,我会指出,我不认为这个代码是一个典型的<代码> ARGMAX < /Case>实现;它不会重复对通常的<代码> ARGMAX < /C>函数在任意数据上的结果。但是它应该可以与这种热编码数据一起使用(仅)。