add code to 01 that repeatedly writes buffers to show overhead; change vector names in kernel code to v1,v2,v3 to show that they're not the same as A,B,C in the C++ code

This commit is contained in:
Dakota St. Laurent
2015-06-09 16:07:18 -04:00
parent ea3055fbc1
commit ef9df7f67c
2 changed files with 58 additions and 12 deletions

View File

@@ -3,7 +3,7 @@
#include <ctime>
double time_add_vectors(int n, int k) {
double timeAddVectorsCPU(int n, int k) {
// adds two vectors of size n, k times, returns total duration
std::clock_t start;
double duration;
@@ -26,7 +26,6 @@ double time_add_vectors(int n, int k) {
return duration;
}
int main() {
// get all platforms (drivers), e.g. NVIDIA
std::vector<cl::Platform> all_platforms;
@@ -58,7 +57,7 @@ int main() {
std::string kernel_code=
// is equivalent to the host's "time_add_vectors" function, except the
// timing will be done on the host.
" void kernel looped_add(global const int* A, global const int* B, global int* C, "
" void kernel looped_add(global const int* v1, global const int* v2, global int* v3, "
" global const int* constants) {"
" int ID, Nthreads, n, k, ratio, start, stop;"
" ID = get_global_id(0);"
@@ -73,9 +72,23 @@ int main() {
" int i, j;" // will the compiler optimize this anyway? probably.
" for (i=0; i<k; i++) {"
" for (j=start; j<stop; j++)"
" C[j] = A[j] + B[j];"
" barrier(CLK_GLOBAL_MEM_FENCE);"
" v3[j] = v1[j] + v2[j];"
" }"
" }"
""
" void kernel add(global const int* v1, global const int* v2, global int* v3, "
" global const int* constants) {"
" int ID, Nthreads, n, ratio, start, stop;"
" ID = get_global_id(0);"
" Nthreads = get_global_size(0);"
" n = constants[0];"
""
" ratio = (n / Nthreads);"
" start = ratio * ID;"
" stop = ratio * (ID+1);"
""
" for (int i=start; i<stop; i++)"
" v3[i] = v1[i] + v2[i];"
" }";
sources.push_back({kernel_code.c_str(), kernel_code.length()});
@@ -92,13 +105,14 @@ int main() {
int constants[2] = {n, k};
// run the CPU code
float CPUtime = time_add_vectors(n, k);
float CPUtime = timeAddVectorsCPU(n, k);
// run some GPU code; this block allocates space, writes buffers, and then
// adds the same two vectors multiple times -- i.e. it's equivalent to the
// host (CPU) code above, but with some necessary overhead.
cl::CommandQueue queue(context, default_device);
cl::KernelFunctor looped_add(cl::Kernel(program, "looped_add"), queue, cl::NullRange, cl::NDRange(Nthreads), cl::NullRange);
cl::KernelFunctor add(cl::Kernel(program, "add"), queue, cl::NullRange, cl::NDRange(Nthreads), cl::NullRange);
// construct vectors
int A[n], B[n], C[n];
@@ -125,20 +139,46 @@ int main() {
queue.enqueueWriteBuffer(buffer_constants, CL_TRUE, 0, sizeof(int)*2, constants);
// RUN ZE KERNEL
std::cout << "Running...";
looped_add(buffer_A, buffer_B, buffer_C, buffer_constants);
std::cout << "Cool." << std::endl;
// read result from GPU to here
// read result from GPU to here; including for the sake of timing
queue.enqueueReadBuffer(buffer_C, CL_TRUE, 0, sizeof(int)*n, C);
GPUtime1 = (std::clock() - start_time) / (double) CLOCKS_PER_SEC;
// do the same thing, except copy the arrays over every iteration
double GPUtime2;
start_time = std::clock();
cl::Buffer buffer_A2(context, CL_MEM_READ_WRITE, sizeof(int)*n);
cl::Buffer buffer_B2(context, CL_MEM_READ_WRITE, sizeof(int)*n);
cl::Buffer buffer_C2(context, CL_MEM_READ_WRITE, sizeof(int)*n);
cl::Buffer buffer_constants2(context, CL_MEM_READ_ONLY, sizeof(int)*2);
for (int i=0; i<k; i++) {
queue.enqueueWriteBuffer(buffer_A2, CL_TRUE, 0, sizeof(int)*n, A);
queue.enqueueWriteBuffer(buffer_B2, CL_TRUE, 0, sizeof(int)*n, B);
queue.enqueueWriteBuffer(buffer_constants2, CL_TRUE, 0, sizeof(int)*2, constants);
add(buffer_A2, buffer_B2, buffer_C2, buffer_constants2);
}
queue.enqueueReadBuffer(buffer_C2, CL_TRUE, 0, sizeof(int)*n, C);
GPUtime2 = (std::clock() - start_time) / (double) CLOCKS_PER_SEC;
// let's compare!
double time_ratio = (CPUtime / GPUtime1);
std::cout << "VERSION 1 -----------" << std::endl;
std::cout << "CPU time: " << CPUtime << std::endl;
std::cout << "GPU time: " << GPUtime1 << std::endl;
std::cout << "GPU is ";
if (time_ratio > 1)
std::cout << time_ratio << " times faster!" << std::endl;
else
std::cout << time_ratio << " times slower :(" << std::endl;
time_ratio = (CPUtime / GPUtime2);
std::cout << "\nVERSION 2 -----------" << std::endl;
std::cout << "CPU time: " << CPUtime << std::endl;
std::cout << "GPU time: " << GPUtime2 << std::endl;
std::cout << "GPU is ";
if (time_ratio > 1)
std::cout << time_ratio << " times faster!" << std::endl;
else