如何像python那样编写cuda c argmax内核,并让它解码一个热矩阵?
如标题所示 这是代码 其中show_data()和get_data()是显示和导入数据的函数 我不知道如何通过一个列主要的单键矩阵(可以放入cublas函数)列出,并像python的argmax函数一样对其进行解码 我知道我一定是把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))+(
$ 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;iif (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>函数在任意数据上的结果。但是它应该可以与这种热编码数据一起使用(仅)。