Osnove
func main() {
// preberemo argumente iz ukazne vrstice
bPtr := flag.Int("b", 1, "num blocks")
tPtr := flag.Int("t", 1, "num threads")
flag.Parse()
// inicializiramo napravo
dev, err := cuda.Init(0)
if err != nil {
panic(err)
}
defer dev.Close()
// zaženemo kodo na napravi
gridSize := cuda.Dim3{X: uint32(*bPtr), Y: 1, Z: 1}
blockSize := cuda.Dim3{X: uint32(*tPtr), Y: 1, Z: 1}
err := cudago.Hello(gridSize, blockSize)
if err != nil {
panic(err)
}
}__global__ void Hello() {
printf("Hello from thread %d.%d!\n", blockIdx.x, threadIdx.x);
}Prenašanje v pomnilnik
Rezervacija pomnilnika na gostitlju in globalnega pomnilnika na napravi:
hm := make(...)
dm, err := cuda.DeviceMemAlloc(count uint64)Prenašanje podatkov med pomnilnikom gostitelja in globalnim pomnilnikom naprave:
err = dm.MemcpyToDevice(hmPtr *unsafe.Pointer, count uint64)
err = dm.MemcpyFromDevice(hmPtr unsafe.Pointer, count uint64)Razlika vektorjev
func main() {
// preberemo argumente iz ukazne vrstice
numBlocksPtr := flag.Int("b", 1, "num blocks")
numThreadsPtr := flag.Int("t", 1, "num threads")
vectorSizePtr := flag.Int("s", 1, "vector size")
flag.Parse()
if *numBlocksPtr < 0 || *numThreadsPtr <= 0 || *vectorSizePtr <= 0 {
panic("Wrong arguments")
}
// izračunamo potrebno število blokov
numBlocks := *numBlocksPtr
if numBlocks == 0 {
numBlocks = (*vectorSizePtr-1) / *numThreadsPtr + 1
}
var err error
// inicializiramo napravo
dev, err := cuda.Init(0)
if err != nil {
panic(err)
}
defer dev.Close()
// rezerviramo pomnilnik na gostitelju
hc := make([]float32, *vectorSizePtr)
ha := make([]float32, *vectorSizePtr)
hb := make([]float32, *vectorSizePtr)
// rezerviramo pomnilnik na napravi
bytesFloat32 := int(unsafe.Sizeof(float32(0.0)))
bytesVector := uint64(*vectorSizePtr * bytesFloat32)
dc, err := cuda.DeviceMemAlloc(bytesVector)
if err != nil {
panic(err)
}
defer dc.Free()
da, err := cuda.DeviceMemAlloc(bytesVector)
if err != nil {
panic(err)
}
defer da.Free()
db, err := cuda.DeviceMemAlloc(bytesVector)
if err != nil {
panic(err)
}
defer db.Free()
// nastavimo vrednosti vektorjev a in b na gostitelju
for i := 0; i < *vectorSizePtr; i++ {
ha[i] = rand.Float32()
hb[i] = rand.Float32()
}
// prenesemo vektorja a in b iz gostitelja na napravo
err = da.MemcpyToDevice(unsafe.Pointer(&ha[0]), bytesVector)
if err != nil {
panic(err)
}
err = db.MemcpyToDevice(unsafe.Pointer(&hb[0]), bytesVector)
if err != nil {
panic(err)
}
// zaženemo kodo na napravi
gridSize := cuda.Dim3{X: uint32(numBlocks), Y: 1, Z: 1}
blockSize := cuda.Dim3{X: uint32(*numThreadsPtr), Y: 1, Z: 1}
err = cudago.VectorSubtract4(gridSize, blockSize, dc.Ptr, da.Ptr, db.Ptr, int32(*vectorSizePtr))
if err != nil {
panic(err)
}
// vektor c prekopiramo iz naprave na gostitelja
err = dc.MemcpyFromDevice(unsafe.Pointer(&hc[0]), bytesVector)
// počakamo, da se procesiranje zahtev na napravi zaključi
err = cuda.CurrentContextSynchronize()
if err != nil {
panic(err)
}
}__global__ void vectorSubtract4(float *c, const float *a, const float *b, int len) {
// določimo globalni indeks elementov
int gid = blockIdx.x * blockDim.x + threadIdx.x;
// št. niti < dolžina vektorjev => morajo nekatere izračunati več razlik
while (gid < len) {
c[gid] = a[gid] - b[gid];
gid += gridDim.x * blockDim.x;
}
}Razdalja vektorjev
func main() {
// Inicializacija
...
// velikosti struktur v bajtih
bytesFloat32 := int(unsafe.Sizeof(float32(0.0)))
bytesVector := uint64(*vectorSizePtr * bytesFloat32)
bytesPartialSum := uint64(numBlocks * bytesFloat32)
bytesLocalMemory := uint64(*numThreadsPtr * bytesFloat32)
// rezerviramo pomnilnik na napravi
...
// nastavimo vrednosti vektorjev a in b na gostitelju
...
// prenesemo vektorja a in b iz gostitelja na napravo
...
// zaženemo kodo na napravi
gridSize := cuda.Dim3{X: uint32(numBlocks), Y: 1, Z: 1}
blockSize := cuda.Dim3{X: uint32(*numThreadsPtr), Y: 1, Z: 1}
err = cudago.VectorDistanceLD4Ex(gridSize, blockSize, bytesLocalMemory, nil, dp.Ptr, da.Ptr, db.Ptr, int32(*vectorSizePtr))
if err != nil {
panic(err)
}
// počakamo, da se procesiranje zahtev na napravi zaključi
...
// vektor p prekopiramo iz naprave na gostitelja
err = dp.MemcpyFromDevice(unsafe.Pointer(&hp[0]), bytesPartialSum)
// dokončamo izračun razdalje za napravo
distDevice := float64(0.0)
for i := 0; i < numBlocks; i++ {
distDevice += float64(hp[i])
}
distDevice = math.Sqrt(distDevice)
}__global__ void vectorDistanceLD4(float *p, const float *a, const float *b, int len) {
// skupni pomnilnik niti v bloku
extern __shared__ float part[];
part[threadIdx.x] = 0.0;
// kvadriranje razlike
int gid = blockIdx.x * blockDim.x + threadIdx.x;
float diff;
while (gid < len) {
diff = a[gid] - b[gid];
part[threadIdx.x] += diff * diff;
gid += gridDim.x * blockDim.x;
}
// počakamo, da vse niti zaključijo
__syncthreads();
// izračunamo delno vsoto za blok niti
int idxStep;
for(idxStep = blockDim.x >> 1; idxStep > 32 ; idxStep >>= 1) {
if (threadIdx.x < idxStep)
part[threadIdx.x] += part[threadIdx.x+idxStep];
__syncthreads();
}
for( ; idxStep > 0 ; idxStep >>= 1 ) {
if (threadIdx.x < idxStep)
part[threadIdx.x] += part[threadIdx.x+idxStep];
__syncwarp();
}
if (threadIdx.x == 0)
p[blockIdx.x] = part[0];
}