Hy
I try to do some performance tests. Therefore, i extended the project “Bandwidthtest” from the Nvidia Cuda examples. The results i attached. I expected other results. I thought, the bandwidth would increase with more data. :blink:
Now my questions:
-
Is my code a good way to measure bandwidth between shared memory andy global memory?
-
Can somebody imagine, why the curve is like that?
Thanks
Lanzelot
Here my code. It works without changing anything.
// includes, system
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
//#include <iostream>
// includes, project
#include <cutil.h>
#include <cuda.h>
// defines Startwerte
#define MODE RANGE_MODE
#define START SHMOO_INCREMENT_1KB
#define END (16* (1<<10))
#define INCREMENT SHMOO_INCREMENT_1KB
#define FILENAME "ergebnis.csv"
#define PRINTCSV 1
// defines, project
#define MEMCOPY_ITERATIONS 10
#define DEFAULT_SIZE ( 32 * ( 1 << 20 ) ) //32 M
#define DEFAULT_INCREMENT (1 << 22) //4 M
#define CACHE_CLEAR_SIZE (1 << 24) //16 M
//shmoo mode defines
#define SHMOO_MEMSIZE_MAX (1 << 26) //64 M
#define SHMOO_MEMSIZE_START (1 << 10) //1 KB
#define SHMOO_INCREMENT_1KB (1 << 10) //1 KB
#define SHMOO_INCREMENT_2KB (1 << 11) //2 KB
#define SHMOO_INCREMENT_10KB (10 * (1 << 10)) //10KB
#define SHMOO_INCREMENT_100KB (100 * (1 << 10)) //100 KB
#define SHMOO_INCREMENT_1MB (1 << 20) //1 MB
#define SHMOO_INCREMENT_2MB (1 << 21) //2 MB
#define SHMOO_INCREMENT_4MB (1 << 22) //4 MB
#define SHMOO_LIMIT_20KB (20 * (1 << 10)) //20 KB
#define SHMOO_LIMIT_50KB (50 * (1 << 10)) //50 KB
#define SHMOO_LIMIT_100KB (100 * (1 << 10)) //100 KB
#define SHMOO_LIMIT_1MB (1 << 20) //1 MB
#define SHMOO_LIMIT_16MB (1 << 24) //16 MB
#define SHMOO_LIMIT_32MB (1 << 25) //32 MB
//enums, project
enum memcpyKind { DEVICE_TO_HOST, HOST_TO_DEVICE, DEVICE_TO_DEVICE, DEVICE_TO_SHARED, SHARED_TO_DEVICE };
enum memoryMode { PINNED, PAGEABLE };
////////////////////////////////////////////////////////////////////////////////
// declaration, forward
float testDeviceToSharedTransfer(unsigned int memSize, memoryMode memMode);
float testSharedToDeviceTransfer(unsigned int memSize, memoryMode memMode);
////////////////////////////////////////////////////////////////////////////////
// Program main
////////////////////////////////////////////////////////////////////////////////
int
main( int argc, char** argv)
{
//test shared to global Memory, 1kB to 16 kB
for(int i=SHMOO_INCREMENT_1KB;i<16*SHMOO_INCREMENT_1KB;i=i+SHMOO_INCREMENT_1KB){
printf("%f\n",testSharedToDeviceTransfer(i, PAGEABLE));
}
printf("\n");
//test global to shared Memory, 1kB to 16 kB
for(int i=SHMOO_INCREMENT_1KB;i<16*SHMOO_INCREMENT_1KB;i=i+SHMOO_INCREMENT_1KB){
printf("%f\n",testSharedToDeviceTransfer(i, PAGEABLE));
}
}
/**
Kernel für den device to shared Transfer
*/
__global__ void kernelDeviceToSharedTransfer(unsigned char* globalArray){
//allocate shared memory
extern __shared__ unsigned char sharedmemory[];
unsigned char* shared = (unsigned char*) sharedmemory;
shared[blockIdx.x*blockDim.x+threadIdx.x] = globalArray[blockIdx.x*blockDim.x+threadIdx.x];
}
/**
Kernel für den shared to device Transfer
*/
__global__ void kernelSharedToDeviceTransfer( unsigned char* globalArrayKopie){
//allocate shared memory
extern __shared__ unsigned char sharedmemory[];
unsigned char* shared = (unsigned char*) sharedmemory;
globalArrayKopie[blockIdx.x*blockDim.x+threadIdx.x] = shared[blockIdx.x*blockDim.x+threadIdx.x];
}
///////////////////////////////////////////////////////////////////////////////
// test the bandwidth of a device to shared memcopy of a specific size
///////////////////////////////////////////////////////////////////////////////
float
testDeviceToSharedTransfer(unsigned int memSize, memoryMode memMode)
{
CUT_DEVICE_INIT();
unsigned int timer = 0;
float elapsedTimeInMs = 0.0f;
float bandwidthInMBs = 0.0f;
unsigned char *h_idata = NULL;
unsigned char *h_idataKopie = NULL;
unsigned char* hostArray = (unsigned char*)malloc(memSize);
CUT_SAFE_CALL( cutCreateTimer( &timer ) );
//allocate host memory
h_idata = (unsigned char *)malloc( memSize );
h_idataKopie = (unsigned char *)malloc( memSize );
//initialize the memory
for(unsigned int i = 0; i < memSize/sizeof(unsigned char); i++)
{
h_idata[i] = (unsigned char) (i & 0xff);
h_idataKopie[i] = (unsigned char) (0x01);
}
// allocate device memory
unsigned char* d_idata;
CUDA_SAFE_CALL( cudaMalloc( (void**) &d_idata, memSize));
unsigned char* d_idataKopie;
CUDA_SAFE_CALL( cudaMalloc( (void**) &d_idataKopie, memSize));
//initialize the device memory
CUDA_SAFE_CALL( cudaMemcpy( d_idata, h_idata, memSize,
cudaMemcpyHostToDevice) );
CUDA_SAFE_CALL( cudaMemcpy( d_idataKopie, h_idataKopie, memSize,
cudaMemcpyHostToDevice) );
//start timer
CUT_SAFE_CALL( cutStartTimer( timer));
//copy data from GPU to shared
kernelDeviceToSharedTransfer<<<16, memSize/16, (memSize)>>>(d_idata);
//get the the total elapsed time in ms
CUT_SAFE_CALL( cutStopTimer( timer));
elapsedTimeInMs = cutGetTimerValue( timer);
//Kopie vom device zum Host kopieren
CUDA_SAFE_CALL( cudaMemcpy(hostArray, d_idataKopie, memSize, cudaMemcpyDeviceToHost));
//calculate bandwidth in MB/s
bandwidthInMBs = (1e3 * memSize * (float)MEMCOPY_ITERATIONS) /
(elapsedTimeInMs * (float)(1 << 20));
//clean up memory
CUT_SAFE_CALL( cutDeleteTimer( timer));
if( PINNED == memMode )
{
CUDA_SAFE_CALL( cudaFreeHost(h_idata) );
CUDA_SAFE_CALL( cudaFreeHost(h_idataKopie) );
}
else
{
free(h_idata);
}
CUDA_SAFE_CALL(cudaFree(d_idata));
return bandwidthInMBs;
}
///////////////////////////////////////////////////////////////////////////////
// test the bandwidth of a shared to device memcopy of a specific size
///////////////////////////////////////////////////////////////////////////////
float
testSharedToDeviceTransfer(unsigned int memSize, memoryMode memMode)
{
CUT_DEVICE_INIT();
unsigned int timer = 0;
float elapsedTimeInMs = 0.0f;
float bandwidthInMBs = 0.0f;
unsigned char *h_idataKopieDtoStoD = NULL;
unsigned char *hostArray = (unsigned char*)malloc(memSize);
CUT_SAFE_CALL( cutCreateTimer( &timer ) );
//allocate host memory
h_idataKopieDtoStoD = (unsigned char *)malloc( memSize );
//initialize the memory
for(unsigned int i = 0; i < memSize/sizeof(unsigned char); i++)
{
h_idataKopieDtoStoD[i] = (unsigned char) (0x01);
}
// allocate device memory
unsigned char* d_idata;
CUDA_SAFE_CALL( cudaMalloc( (void**) &d_idata, memSize));
unsigned char* d_idataKopieDtoStoD;
CUDA_SAFE_CALL( cudaMalloc( (void**) &d_idataKopieDtoStoD, memSize));
//initialize the device memory
CUDA_SAFE_CALL( cudaMemcpy( d_idataKopieDtoStoD, h_idataKopieDtoStoD, memSize,
cudaMemcpyHostToDevice) );
CUT_SAFE_CALL( cutStartTimer( timer));
//copy data from GPU to shared to GPU
kernelSharedToDeviceTransfer<<<16, memSize/16, (memSize)>>>(d_idataKopieDtoStoD);
CUDA_SAFE_CALL( cudaThreadSynchronize() );
//get the the total elapsed InitTime in ms
elapsedTimeInMs = cutGetTimerValue( timer);
//Kopie vom device zum Host kopieren
CUDA_SAFE_CALL( cudaMemcpy(hostArray, d_idataKopieDtoStoD, memSize, cudaMemcpyDeviceToHost));
//printf("%f\n",elapsedTimeInMs);
bandwidthInMBs = ((1e3 * memSize * (float)MEMCOPY_ITERATIONS) /
(( elapsedTimeInMs) * (float)(1 << 20)));
//clean up memory
CUT_SAFE_CALL( cutDeleteTimer( timer));
if( PINNED == memMode )
{
CUDA_SAFE_CALL( cudaFreeHost(h_idataKopieDtoStoD) );
}
else
{
free(h_idataKopieDtoStoD);
}
CUDA_SAFE_CALL(cudaFree(d_idata));
return bandwidthInMBs;
}
