{"id":755,"date":"2018-06-01T20:44:50","date_gmt":"2018-06-01T10:44:50","guid":{"rendered":"http:\/\/www.nickdu.com\/?p=755"},"modified":"2018-06-01T20:44:50","modified_gmt":"2018-06-01T10:44:50","slug":"learning-opencl-programming","status":"publish","type":"post","link":"https:\/\/nickdu.com\/?p=755","title":{"rendered":"Learning OpenCL programming"},"content":{"rendered":"<p>This post is to record the steps how I run my first &#8220;Hello World&#8221; <a href=\"https:\/\/en.wikipedia.org\/wiki\/OpenCL\" target=\"_blank\" rel=\"noopener\">OpenCL<\/a> C++ program.<\/p>\n<ol>\n<li>To make things easier, I created this,\u00a0<a href=\"http:\/\/www.nickdu.com\/wp-content\/uploads\/2018\/06\/OpenCL.zip\" target=\"_blank\" rel=\"noopener\">OpenCL.zip<\/a>, OpenCL library and C\/C++ header files.<\/li>\n<li>Create a Visual Studio C++ project<\/li>\n<li>The following code is to add two 2^25 array altogether using GPU:<\/li>\n<\/ol>\n<pre lang=\"cpp\">#include &lt;iostream&gt;\n#include &lt;vector&gt;\n#include &lt;string&gt;\nusing namespace std;\n\n#define __CL_ENABLE_EXCEPTIONS\n#include &lt;CL\\cl.hpp&gt;\n\n\/\/ Compute c = a + b.\nstatic const char source[] =\n\"kernel void add(\\n\"\n\"       ulong n,\\n\"\n\"       global const float *a,\\n\"\n\"       global const float *b,\\n\"\n\"       global float *c\\n\"\n\"       )\\n\"\n\"{\\n\"\n\"    size_t i = get_global_id(0);\\n\"\n\"    if (i &lt; n) {\\n\"\n\"       c[i] = a[i] + b[i];\\n\"\n\"    }\\n\"\n\"}\\n\";\n\nint main() {\n\n\tconst size_t N = 1 &lt;&lt; 25;\n\n\ttry {\n\t\t\/\/ Get list of OpenCL platforms.\n\t\tstd::vector platform;\n\t\tcl::Platform::get(&amp;platform);\n\n\t\tif (platform.empty()) {\n\t\t\tstd::cerr &lt;&lt; \"OpenCL platforms not found.\" &lt;&lt; std::endl;\n\t\t\treturn 1;\n\t\t}\n\n\t\t\/\/ Get first available GPU device.\n\t\tcl::Context context;\n\t\tstd::vector device;\n\t\tfor (auto p = platform.begin(); device.empty() &amp;&amp; p != platform.end(); p++) {\n\t\t\tstd::vector pldev;\n\n\t\t\ttry {\n\t\t\t\tp-&gt;getDevices(CL_DEVICE_TYPE_DEFAULT, &amp;pldev);\n\n\t\t\t\tfor (auto d = pldev.begin(); device.empty() &amp;&amp; d != pldev.end(); d++) {\n\t\t\t\t\tif (!d-&gt;getInfo()) continue;\n\n\t\t\t\t\tstd::string ext = d-&gt;getInfo();\n\n\t\t\t\t\tdevice.push_back(*d);\n\t\t\t\t\tcontext = cl::Context(device);\n\t\t\t\t}\n\t\t\t}\n\t\t\tcatch (...) {\n\t\t\t\tdevice.clear();\n\t\t\t}\n\t\t}\n\n\t\tif (device.empty()) {\n\t\t\tstd::cerr &lt;&lt; \"GPUs device not found.\" &lt;&lt; std::endl;\n\t\t\treturn 1;\n\t\t}\n\n\t\tstd::cout &lt;&lt; device[0].getInfo() &lt;&lt; std::endl;\n\n\t\t\/\/ Create command queue.\n\t\tcl::CommandQueue queue(context, device[0]);\n\n\t\t\/\/ Compile OpenCL program for found device.\n\t\tcl::Program program(context, cl::Program::Sources(\n\t\t\t1, std::make_pair(source, strlen(source))\n\t\t\t));\n\n\t\ttry {\n\t\t\tprogram.build(device);\n\t\t}\n\t\tcatch (const cl::Error&amp;) {\n\t\t\tstd::cerr\n\t\t\t\t&lt;&lt; \"OpenCL compilation error\" &lt;&lt; std::endl\n\t\t\t\t&lt;&lt; program.getBuildInfo(device[0])\n\t\t\t\t&lt;&lt; std::endl;\n\t\t\treturn 1;\n\t\t}\n\n\t\tcl::Kernel add(program, \"add\");\n\n\t\t\/\/ Prepare input data.\n\t\tstd::vector a(N, 1);\n\t\tstd::vector b(N, 2);\n\t\tstd::vector c(N);\n\n\t\t\/\/ Allocate device buffers and transfer input data to device.\n\t\tcl::Buffer A(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,\n\t\t\ta.size() * sizeof(float), a.data());\n\n\t\tcl::Buffer B(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,\n\t\t\tb.size() * sizeof(float), b.data());\n\n\t\tcl::Buffer C(context, CL_MEM_READ_WRITE,\n\t\t\tc.size() * sizeof(float));\n\n\t\t\/\/ Set kernel parameters.\n\t\tadd.setArg(0, static_cast(N));\n\t\tadd.setArg(1, A);\n\t\tadd.setArg(2, B);\n\t\tadd.setArg(3, C);\n\n\t\t\/\/ Launch kernel on the compute device.\n\t\tqueue.enqueueNDRangeKernel(add, cl::NullRange, N, cl::NullRange);\n\n\t\t\/\/ Get result back to host.\n\t\tqueue.enqueueReadBuffer(C, CL_TRUE, 0, c.size() * sizeof(float), c.data());\n\n\t\t\/\/ Should get '3' here.\n\t\tstd::cout &lt;&lt; c[42] &lt;&lt; std::endl;\n\t}\n\tcatch (const cl::Error &amp;err) {\n\t\tstd::cerr\n\t\t\t&lt;&lt; \"OpenCL error: \"\n\t\t\t&lt;&lt; err.what() &lt;&lt; \"(\" &lt;&lt; err.err() &lt;&lt; \")\"\n\t\t\t&lt;&lt; std::endl;\n\t\treturn 1;\n\t}\n}\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>This post is to record the steps how I run my first &#8220;Hello World&#8221; OpenCL C++ program. To make things easier, I created this,\u00a0OpenCL.zip, OpenCL library and C\/C++ header files. Create a Visual Studio C++ project The following code is to add two 2^25 array altogether using GPU: #include &lt;iostream&gt; #include &lt;vector&gt; #include &lt;string&gt; using &hellip; <a href=\"https:\/\/nickdu.com\/?p=755\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Learning OpenCL programming&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12,2],"tags":[],"class_list":["post-755","post","type-post","status-publish","format-standard","hentry","category-cc","category-it"],"_links":{"self":[{"href":"https:\/\/nickdu.com\/index.php?rest_route=\/wp\/v2\/posts\/755","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nickdu.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nickdu.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nickdu.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nickdu.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=755"}],"version-history":[{"count":0,"href":"https:\/\/nickdu.com\/index.php?rest_route=\/wp\/v2\/posts\/755\/revisions"}],"wp:attachment":[{"href":"https:\/\/nickdu.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=755"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nickdu.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=755"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nickdu.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=755"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}