I would like to pass a string to my GPU and get it back from the GPU to print it. It is for understanding purposes - I know, the idea sounds senseless.
I tried:
OpenCL:
__kernel void same_in_same_out_char(__global uchar * out, __constant uchar * in){
for (unsigned int ui=0; ui<3; ui++) out[ui]=in[ui];
}
C++:
#define __CL_ENABLE_EXCEPTIONS
#include <fstream>
#include <iostream>
#include <iterator>
#include <CL/cl.hpp>
#include <CL/opencl.h>
using namespace std;
int main () {
vector<cl::Platform> platforms;
vector<cl::Device> devices;
vector<cl::Kernel> kernels;
try {
// create platform
cl::Platform::get(&platforms);
platforms[0].getDevices(CL_DEVICE_TYPE_GPU, &devices);
// create context
cl::Context context(devices);
// create command queue
cl::CommandQueue queue(context, devices[0]);
// load opencl source
ifstream cl_file("inout.cl");
string cl_string(istreambuf_iterator<char>(cl_file), (istreambuf_iterator<char>()));
cl::Program::Sources source(1, make_pair(cl_string.c_str(),
cl_string.length() + 1));
// create program
cl::Program program(context, source);
// compile opencl source
program.build(devices);
// load named kernel from opencl source
cl::Kernel kernel(program, "same_in_same_out_char");
// create a message to send to kernel
const char pwd[] = "MAX";
cout << "char pwd[] : " << pwd << endl;
cl_uchar * password = (cl_uchar*) &pwd;
int bufferA_size = 3; // array size is 3
int bufferC_size = 3; // array size is 3
cout << " -- OpenCL -- " << endl;
// allocate device buffer to hold message
cl::Buffer bufferA(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(cl_uchar) * bufferA_size, password);
cl::Buffer bufferC(context, CL_MEM_WRITE_ONLY, sizeof(cl_uchar) * bufferC_size);
// set message as kernel argument
kernel.setArg(0, bufferC);
kernel.setArg(1, bufferA);
// execute kernel
queue.enqueueTask(kernel);
// wait for completion
queue.finish();
// ----------------------
cl_uint out_global[bufferC_size];
queue.enqueueReadBuffer(bufferC, CL_TRUE, 0, bufferC_size*sizeof(cl_uchar), &out_global);
cout << "Output \t\t:" << *out_global << endl << "Output[1..n] \t:";
for (unsigned int i=0; i<bufferC_size; i ++) cout << out_global[i] << " " ;
cout << endl;
} catch (cl::Error e) {
cout << endl << e.what() << " : " << e.err() << endl;
}
return 0;
}
But I failed. Output is
Output :5783885
Output[1..n] :5783885 0 26
But not
MAX or 77 65 88
(for M A X).
Regard, Marcus
It is if fact giving you the answer you expect, but you are putting it in the wrong data type.
What you are getting is the single integer 5783885, which is 0x0058414D (in hexadecimal.) You are on a little-endian platform, so these bytes are arranged in memory from low-order to high-order, i.e. if you look at the memory, the bytes will be (still in hex):
4D, 41, 58, 00, ...
These, displayed in decimal will be:
77, 65, 88, 0, ...
In other words, exactly what you expect.
Your problem (one of your problems, at least) is that you've declared out_global as an array of cl_uints, instead of cl_uchar or cl_char or something.
So change the following line, and you'll probably be fine.
cl_uint out_global[bufferC_size];
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With