cuda编程 c
与其他语言相比,使用Go编程CUDA有点复杂。 尽管有一些出色的软件包,例如mumax ,但是文档很差,缺少示例并且很难使用。
CUDA用于C语言 ,所以最好的选择是使用Command cgo并使用您的Cuda内核调用外部函数。 这就是我在此示例中所做的事情,在该示例中,我使用CUDA将两个矩阵相乘。
如果您想了解有关CUDA编程的更多信息,请阅读我的文章 。
核心
我创建了一个简单的内核 ,该内核具有内核功能和可在外部调用的辅助功能。 请注意,我使用了extern C,因为这是cgo调用函数的方式:
# include <stdio.h>
# include <cuda.h>
__ global__ void vecmul ( float *A, float * B, float *C, int size)
{
// Row and Column indexes:
int row = blockIdx.y*blockDim.y+threadIdx.y;
int col = blockIdx.x*blockDim.x+threadIdx.x;
// Are they bellow the maximum?
if (col < size && row < size) {
float result = 0 ;
for ( int ix= 0 ;ix<size;ix++) {
result += A[row*size+ix]*B[ix*size+col];
}
C[row*size+col] = result;
}
}
extern "C" {
void maxmul ( float *A, float * B, float *C, int size) {
int total = size*size;
// Allocate device memory:
float * gpu_A;
float * gpu_B;
float * gpu_C;
int msize = total * sizeof ( float );
cudaMalloc(( void **)&gpu_A, msize);
cudaMemcpy(gpu_A,A,msize,cudaMemcpyHostToDevice);
cudaMalloc(( void **)&gpu_B, msize);
cudaMemcpy(gpu_B,B,msize,cudaMemcpyHostToDevice);
cudaMalloc(( void **)&gpu_C,msize);
// Blocks & grids:
dim3 blocks (size,size) ;
dim3 grid ( 1 , 1 ) ;
// Call the kernel:
vecmul<<<grid,blocks>>>(gpu_A,gpu_B,gpu_C,size);
// Get the result Matrix:
cudaMemcpy(C,gpu_C,msize,cudaMemcpyDeviceToHost);
//Free device matrices
cudaFree(gpu_A);
cudaFree(gpu_B);
cudaFree(gpu_C);
}
}
vecmul()函数是内核, maxmul()函数是助手。 它的功能是在GPU中分配内存,复制参数,调用内核并复制结果。 值通过引用传递。
转到代码
程序maxmul.go调用helper函数并显示结果:
package main
/*
void maxmul(float *A, float* B, float *C, int size);
#cgo LDFLAGS: -L. -L./ -lmaxmul
*/
import "C"
import "fmt"
func Maxmul (a []C.float, b []C.float, c []C.float, size int ) {
C.maxmul(&a[ 0 ], &b[ 0 ], &c[ 0 ], C. int (size))
}
func main () {
//in := []C.float{1.23, 4.56}
//C.test(&in[0]) // C 1.230000 4.560000
a := []C.float{ -1 , 2 , 4 , 0 , 5 , 3 , 6 , 2 , 1 }
b := []C.float{ 3 , 0 , 2 , 3 , 4 , 5 , 4 , 7 , 2 }
var c []C.float = make ([]C.float, 9 )
Maxmul(a,b,c, 3 )
fmt.Println(c)
}
在导入允许使用纯C代码(外部C)调用外部函数的C程序包之前,我传递了cgo的配置,指示函数C的原型, lib的路径及其名称。
我必须在Go代码中创建包装函数,以调用外部函数以使事情变得更容易。 它只是将引用传递给数组(第一个位置的地址)和数组大小(在这种情况下为3x3 = 9)。 在CUDA中,我们处理平面矩阵。
我使用C.float类型创建了包含我的数组的切片 (转换为向量)。 然后我调用了该函数。 请注意,我传递了每行(或列)的大小。
编译中
要编译C代码,请使用以下命令:
nvcc --ptxas-options=-v --compiler-options'-fPIC' -o libmaxmul.so --shared maxmul.cu
您需要安装CUDA和Nvidia驱动程序!
然后只需使用以下命令运行Go代码:
go run maxmul.go
...
[19 36 16 27 41 31 28 15 24]
这是矩阵相乘的结果!
完整的源代码在这里: https : //github.com/cleuton/golang-network/tree/master/english/cuda/nostress
翻译自: https://hackernoon.com/no-stress-cuda-programming-using-go-and-c-fy1y3agf
cuda编程 c