diff --git a/exercise6/.gitignore b/exercise6/.gitignore new file mode 100644 index 0000000..c88902b --- /dev/null +++ b/exercise6/.gitignore @@ -0,0 +1,2 @@ +mandel +mandel_c diff --git a/exercise6/Makefile b/exercise6/Makefile new file mode 100644 index 0000000..13f6714 --- /dev/null +++ b/exercise6/Makefile @@ -0,0 +1,9 @@ +PATH+=:/usr/local/cuda/bin +all: mandel_c mandel +mandel: + nvcc -o mandel mandel.cu -O3 -lm +mandel_c: + gcc -o mandel_c mandel_c.c -O3 -Wall -std=c99 -lm +clean: + -rm -f mandel_c mandel + diff --git a/exercise6/mandel.cu b/exercise6/mandel.cu new file mode 100644 index 0000000..5782227 --- /dev/null +++ b/exercise6/mandel.cu @@ -0,0 +1,190 @@ +#include +#include +#include +#include + +/* Problem size */ +#define XSIZE 2560 +#define YSIZE 2048 + +/* Divide the problem into blocks of BLOCKX x BLOCKY threads */ +#define BLOCKY 8 +#define BLOCKX 8 + +#define MAXITER 255 + +double xleft=-2.01; +double xright=1; +double yupper,ylower; +double ycenter=1e-6; +double step; + +int host_pixel[XSIZE*YSIZE]; +int device_pixel[XSIZE*YSIZE]; + +typedef struct { + double real,imag; +} my_complex_t; + +#define PIXEL(i,j) ((i)+(j)*XSIZE) + +/********** SUBTASK1: Create kernel device_calculate *************************/ + +//Insert code here + +/********** SUBTASK1 END *****************************************************/ + +void host_calculate() { + for(int j=0;j>8)&255,(size>>16)&255,size>>24,0, + 0,0,0,54,0,0,0,40,0,0,0,x&255,x>>8,0,0,y&255,y>>8,0,0,1,0,24,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + fwrite(header,1,54,f); + fwrite(buffer,1,x*y*3,f); + fclose(f); +} + +/* given iteration number, set a colour */ +void fancycolour(uchar *p,int iter) { + if(iter==MAXITER); + else if(iter<8) { p[0]=128+iter*16; p[1]=p[2]=0; } + else if(iter<24) { p[0]=255; p[1]=p[2]=(iter-8)*16; } + else if(iter<160) { p[0]=p[1]=255-(iter-24)*2; p[2]=255; } + else { p[0]=p[1]=(iter-160)*2; p[2]=255-(iter-160)*2; } +} + +/* + * Get system time to microsecond precision (ostensibly, the same as MPI_Wtime), + * returns time in seconds + */ +double walltime ( void ) { + static struct timeval t; + gettimeofday ( &t, NULL ); + return ( t.tv_sec + 1e-6 * t.tv_usec ); +} + +int main(int argc,char **argv) { + if(argc==1) { + puts("Usage: MANDEL n"); + puts("n decides whether image should be written to disk (1=yes, 0=no)"); + return 0; + } + double start; + double hosttime=0; + double devicetime=0; + double memtime=0; + + cudaDeviceProp p; + cudaSetDevice(0); + cudaGetDeviceProperties (&p, 0); + printf("Device compute capability: %d.%d\n", p.major, p.minor); + + /* Calculate the range in the y-axis such that we preserve the + aspect ratio */ + step=(xright-xleft)/XSIZE; + yupper=ycenter+(step*YSIZE)/2; + ylower=ycenter-(step*YSIZE)/2; + + /* Host calculates image */ + start=walltime(); + host_calculate(); + hosttime+=walltime()-start; + + /********** SUBTASK2: Set up device memory *******************************/ + + // Insert code here + + /********** SUBTASK2 END *************************************************/ + + start=walltime(); + /********** SUBTASK3: Execute the kernel on the device *******************/ + + //Insert code here + + /********** SUBTASK3 END *************************************************/ + + devicetime+=walltime()-start; + + start=walltime(); + + /********** SUBTASK4: Transfer the result from device to device_pixel[][]*/ + + //Insert code here + + /********** SUBTASK4 END *************************************************/ + + memtime+=walltime()-start; + + /********** SUBTASK5: Free the device memory also ************************/ + + //Insert code here + + /********** SUBTASK5 END *************************************************/ + + int errors=0; + /* check if result is correct */ + for(int i=0;i1) { + if(errors<10) printf("Error on pixel %d %d: expected %d, found %d\n", + i,j,host_pixel[PIXEL(i,j)],device_pixel[PIXEL(i,j)]); + else if(errors==10) puts("..."); + errors++; + } + } + } + if(errors>0) printf("Found %d errors.\n",errors); + else puts("Device calculations are correct."); + + printf("\n"); + printf("Host time: %7.3f ms\n",hosttime*1e3); + printf("Device calculation: %7.3f ms\n",devicetime*1e3); + printf("Copy result: %7.3f ms\n",memtime*1e3); + + if(strtol(argv[1],NULL,10)!=0) { + /* create nice image from iteration counts. take care to create it upside + down (bmp format) */ + unsigned char *buffer=(unsigned char *)calloc(XSIZE*YSIZE*3,1); + for(int i=0;i +#include +#include + +#define XSIZE 2560 +#define YSIZE 2048 + +#define MAXITER 255 + +double xleft=-2.01; +double xright=1; +double yupper,ylower; +double ycenter=1e-6; +double step; + +int pixel[XSIZE*YSIZE]; + +#define PIXEL(i,j) ((i)+(j)*XSIZE) + +typedef struct { + double real,imag; +} complex_t; + +void calculate() { + for(int i=0;i>8)&255,(size>>16)&255,size>>24,0, + 0,0,0,54,0,0,0,40,0,0,0,x&255,x>>8,0,0,y&255,y>>8,0,0,1,0,24,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + fwrite(header,1,54,f); + fwrite(buffer,1,XSIZE*YSIZE*3,f); + fclose(f); +} + +/* given iteration number, set a colour */ +void fancycolour(uchar *p,int iter) { + if(iter==MAXITER); + else if(iter<8) { p[0]=128+iter*16; p[1]=p[2]=0; } + else if(iter<24) { p[0]=255; p[1]=p[2]=(iter-8)*16; } + else if(iter<160) { p[0]=p[1]=255-(iter-24)*2; p[2]=255; } + else { p[0]=p[1]=(iter-160)*2; p[2]=255-(iter-160)*2; } +} + +int main(int argc,char **argv) { + if(argc==1) { + puts("Usage: MANDEL n"); + puts("n decides whether image should be written to disk (1=yes, 0=no)"); + return 0; + } + /* Calculate the range in the y-axis such that we preserve the + aspect ratio */ + step=(xright-xleft)/XSIZE; + yupper=ycenter+(step*YSIZE)/2; + ylower=ycenter-(step*YSIZE)/2; + + calculate(); + + if(strtol(argv[1],NULL,10)!=0) { + /* create nice image from iteration counts. take care to create it upside + down (bmp format) */ + unsigned char *buffer=calloc(XSIZE*YSIZE*3,1); + for(int i=0;i