In questo tutorial mostriamo come generare istogrammi tramite Cuda, ovviamente con funzioni __global__ esterne al main e con il cronometraggio dei tempi di calcolo.
- Novità: implementazione della funzione atomicAdd
// CREAZIONE ISTOGRAMMI
#include < iostream >
#include < cstdlib >
#include "sm_11_atomic_functions.h"
using namespace std;
#define NPUNTI 1000000
#define NBINS 256
#define THREADS 256
#define NBLOCKS 32
//////////////////////////////////////////////////////////////////////////////////
__global__ void histogram( unsigned char *buf, unsigned int *his ){
int trid = threadIdx.x;
int tid = blockDim.x*blockIdx.x + trid;
int jump = gridDim.x*blockDim.x;
__shared__ unsigned int temp[NBINS];
temp[trid] = 0;
__syncthreads();
while (tid < NPUNTI){ // scorro i dati a salti di n*k threads
// atomicAdd: operazione che effettua la modifica della variabile temp con il suo indice
// appena accede all'indirizzo lo locka, lo cambia aggiungendogli il numero e poi lo libera
atomicAdd( &temp[buf[tid]], 1 );
tid += jump; // sto aggiornando l´istogramma finale del blocco blockIdx.x
}
__syncthreads();
atomicAdd( &his[trid], temp[trid] ); // sommo tutti gli istogrammi parziali, un blocco alla volta
};
/////////////////////////////////////////////////////////////////////////////////////
int main (void) {
unsigned char *dev_buf;
unsigned int *dev_his;
unsigned char *buf = (unsigned char *)malloc( NPUNTI*sizeof(unsigned char) );
for (int i=0; i
unsigned int *his = (unsigned int *)malloc( NBINS*sizeof(unsigned int) );
// faccio partire il cronometro
cudaEvent_t start,stop;
cudaEventCreate(&start);
cudaEventCreate(&stop);
cudaEventRecord(start,0);
// alloco memoria sulla scheda grafica
cudaMalloc( (void **)&dev_buf, NPUNTI*sizeof(unsigned char) );
cudaMalloc( (void **)&dev_his, NBINS*sizeof(unsigned int) );
cudaMemset( dev_his, 0, NBINS*sizeof(unsigned int) );
cout << "programming with cuda c\n";
// copio su device, lancio il kernel, copio su host
cudaMemcpy( dev_buf, buf, NPUNTI*sizeof(unsigned char), cudaMemcpyHostToDevice );
histogram<<
cudaMemcpy( his, dev_his, NBINS*sizeof(unsigned int), cudaMemcpyDeviceToHost );
for( int i=0; i
cout << i << "\t" << his[i] << "\n";
};
// fermo il cronometro
cudaEventRecord(stop,0);
cudaEventSynchronize(stop);
float elapsed;
cudaEventElapsedTime(&elapsed,start,stop);
cout << "Time:" << elapsed/1000. << endl;
// dealloco
cudaEventDestroy(start);
cudaEventDestroy(stop);
cudaFree(dev_buf);
cudaFree(dev_his);
free(buf);
free(his);
return 0;
}
Categories:
Cuda
Posta un commento