性能:boost.compute v.s.opencl c++;包装纸 以下代码分别使用BooST.Cube和OpenCL C++包装器添加两个矢量。结果表明,BooSt.Cube的计算速度比OpenCL C++封装器慢20倍。我想知道我是否错过了使用boost.compute或者它确实很慢。 平台:win7、vs2013、boost 1.55、boost.compute 0.2、ATI Radeon HD 4600 代码使用C++包装器: #define __CL_ENABLE_EXCEPTIONS #include <CL/cl.hpp> #include <boost/timer/timer.hpp> #include <boost/smart_ptr/scoped_array.hpp> #include <fstream> #include <numeric> #include <algorithm> #include <functional> int main(){ static char kernelSourceCode[] = "\ __kernel void vadd(__global int * a, __global int * b, __global int * c){\ size_t i = get_global_id(0);\ \ c[i] = a[i] + b[i];\ }\ "; using type = boost::scoped_array<int>; size_t const BUFFER_SIZE = 1UL << 13; type A(new int[BUFFER_SIZE]); type B(new int[BUFFER_SIZE]); type C(new int[BUFFER_SIZE]); std::iota(A.get(), A.get() + BUFFER_SIZE, 0); std::transform(A.get(), A.get() + BUFFER_SIZE, B.get(), std::bind(std::multiplies<int>(), std::placeholders::_1, 2)); try { std::vector<cl::Platform> platformList; // Pick platform cl::Platform::get(&platformList); // Pick first platform cl_context_properties cprops[] = { CL_CONTEXT_PLATFORM, (cl_context_properties)(platformList[0])(), 0 }; cl::Context context(CL_DEVICE_TYPE_GPU, cprops); // Query the set of devices attached to the context std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>(); // Create command-queue cl::CommandQueue queue(context, devices[0], 0); // Create the program from source cl::Program::Sources sources( 1, std::make_pair(kernelSourceCode, 0) ); cl::Program program(context, sources); // Build program program.build(devices); // Create buffer for A and copy host contents cl::Buffer aBuffer = cl::Buffer( context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, BUFFER_SIZE * sizeof(int), (void *)&A[0]); // Create buffer for B and copy host contents cl::Buffer bBuffer = cl::Buffer( context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, BUFFER_SIZE * sizeof(int), (void *)&B[0]); // Create buffer that uses the host ptr C cl::Buffer cBuffer = cl::Buffer( context, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, BUFFER_SIZE * sizeof(int), (void *)&C[0]); // Create kernel object cl::Kernel kernel(program, "vadd"); // Set kernel args kernel.setArg(0, aBuffer); kernel.setArg(1, bBuffer); kernel.setArg(2, cBuffer); // Do the work void *output; { boost::timer::auto_cpu_timer timer; queue.enqueueNDRangeKernel( kernel, cl::NullRange, cl::NDRange(BUFFER_SIZE), cl::NullRange ); output = (int *)queue.enqueueMapBuffer( cBuffer, CL_TRUE, // block CL_MAP_READ, 0, BUFFER_SIZE * sizeof(int) ); } std::ofstream gpu("gpu.txt"); for (int i = 0; i < BUFFER_SIZE; i++) { gpu << C[i] << " "; } queue.enqueueUnmapMemObject( cBuffer, output); } catch (cl::Error const &err) { std::cerr << err.what() << "\n"; } return EXIT_SUCCESS; } \define\u CL\u ENABLE\u异常 #包括 #包括 #包括 #包括 #包括 #包括 #包括 int main(){ 静态字符内核资源代码[]=”\ __内核void vadd(uuu global int*a、uu global int*b、uuu global int*c){\ size\u t i=获取全局\u id(0)\ \ c[i]=a[i]+b[i]\ }\ "; 使用type=boost::作用域数组; 大小常数缓冲区大小=1UL 我几乎可以肯定boost.compute有更大的初始化开销。请尝试更复杂的任务,8Kb的向量加法太容易了 测量这两种情况下OpenCL内核的执行时间。这是相同的,唯一的原因是boost.compute端的开销 检查两种情况下的内存分配标志是否相同 由Boosix.Cube中的函数生成的内核代码应该与C++包装版本中使用的内核代码几乎相同(虽然Boosix.Cudio会进行一些展开)。

性能:boost.compute v.s.opencl c++;包装纸 以下代码分别使用BooST.Cube和OpenCL C++包装器添加两个矢量。结果表明,BooSt.Cube的计算速度比OpenCL C++封装器慢20倍。我想知道我是否错过了使用boost.compute或者它确实很慢。 平台:win7、vs2013、boost 1.55、boost.compute 0.2、ATI Radeon HD 4600 代码使用C++包装器: #define __CL_ENABLE_EXCEPTIONS #include <CL/cl.hpp> #include <boost/timer/timer.hpp> #include <boost/smart_ptr/scoped_array.hpp> #include <fstream> #include <numeric> #include <algorithm> #include <functional> int main(){ static char kernelSourceCode[] = "\ __kernel void vadd(__global int * a, __global int * b, __global int * c){\ size_t i = get_global_id(0);\ \ c[i] = a[i] + b[i];\ }\ "; using type = boost::scoped_array<int>; size_t const BUFFER_SIZE = 1UL << 13; type A(new int[BUFFER_SIZE]); type B(new int[BUFFER_SIZE]); type C(new int[BUFFER_SIZE]); std::iota(A.get(), A.get() + BUFFER_SIZE, 0); std::transform(A.get(), A.get() + BUFFER_SIZE, B.get(), std::bind(std::multiplies<int>(), std::placeholders::_1, 2)); try { std::vector<cl::Platform> platformList; // Pick platform cl::Platform::get(&platformList); // Pick first platform cl_context_properties cprops[] = { CL_CONTEXT_PLATFORM, (cl_context_properties)(platformList[0])(), 0 }; cl::Context context(CL_DEVICE_TYPE_GPU, cprops); // Query the set of devices attached to the context std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>(); // Create command-queue cl::CommandQueue queue(context, devices[0], 0); // Create the program from source cl::Program::Sources sources( 1, std::make_pair(kernelSourceCode, 0) ); cl::Program program(context, sources); // Build program program.build(devices); // Create buffer for A and copy host contents cl::Buffer aBuffer = cl::Buffer( context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, BUFFER_SIZE * sizeof(int), (void *)&A[0]); // Create buffer for B and copy host contents cl::Buffer bBuffer = cl::Buffer( context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, BUFFER_SIZE * sizeof(int), (void *)&B[0]); // Create buffer that uses the host ptr C cl::Buffer cBuffer = cl::Buffer( context, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, BUFFER_SIZE * sizeof(int), (void *)&C[0]); // Create kernel object cl::Kernel kernel(program, "vadd"); // Set kernel args kernel.setArg(0, aBuffer); kernel.setArg(1, bBuffer); kernel.setArg(2, cBuffer); // Do the work void *output; { boost::timer::auto_cpu_timer timer; queue.enqueueNDRangeKernel( kernel, cl::NullRange, cl::NDRange(BUFFER_SIZE), cl::NullRange ); output = (int *)queue.enqueueMapBuffer( cBuffer, CL_TRUE, // block CL_MAP_READ, 0, BUFFER_SIZE * sizeof(int) ); } std::ofstream gpu("gpu.txt"); for (int i = 0; i < BUFFER_SIZE; i++) { gpu << C[i] << " "; } queue.enqueueUnmapMemObject( cBuffer, output); } catch (cl::Error const &err) { std::cerr << err.what() << "\n"; } return EXIT_SUCCESS; } \define\u CL\u ENABLE\u异常 #包括 #包括 #包括 #包括 #包括 #包括 #包括 int main(){ 静态字符内核资源代码[]=”\ __内核void vadd(uuu global int*a、uu global int*b、uuu global int*c){\ size\u t i=获取全局\u id(0)\ \ c[i]=a[i]+b[i]\ }\ "; 使用type=boost::作用域数组; 大小常数缓冲区大小=1UL 我几乎可以肯定boost.compute有更大的初始化开销。请尝试更复杂的任务,8Kb的向量加法太容易了 测量这两种情况下OpenCL内核的执行时间。这是相同的,唯一的原因是boost.compute端的开销 检查两种情况下的内存分配标志是否相同 由Boosix.Cube中的函数生成的内核代码应该与C++包装版本中使用的内核代码几乎相同(虽然Boosix.Cudio会进行一些展开)。,c++,boost,opencl,boost-compute,C++,Boost,Opencl,Boost Compute,您看到计时差异的原因是,在第一个版本中,您只测量将内核排队并将结果映射回主机所需的时间。在Boost.Compute版本中,您还测量创建转换()所需的时间kernel,编译它,然后执行它。如果您想要更真实的比较,您应该测量第一个示例的总执行时间,包括设置和编译OpenCL程序所需的时间 Boost.Compute通过在运行时自动缓存编译后的内核(也可以选择脱机缓存以供下次运行程序时重用),在一定程度上减轻了初始化代价(这是OpenCL运行时编译模型固有的)第一次调用后,多次调用会快得多 另外,您

您看到计时差异的原因是,在第一个版本中,您只测量将内核排队并将结果映射回主机所需的时间。在Boost.Compute版本中,您还测量创建
转换()所需的时间
kernel,编译它,然后执行它。如果您想要更真实的比较,您应该测量第一个示例的总执行时间,包括设置和编译OpenCL程序所需的时间

Boost.Compute通过在运行时自动缓存编译后的内核(也可以选择脱机缓存以供下次运行程序时重用),在一定程度上减轻了初始化代价(这是OpenCL运行时编译模型固有的)第一次调用后,多次调用会快得多


另外,您还可以使用Boost.Compute中的核心包装器类(如和)以及容器类(如)并且仍然运行您自己的自定义内核。

我稍微编辑了代码,这样就不需要考虑创建队列的时间。但是差距仍然很大。现在标记完全相同。我说的是内核执行时间。它可以通过内核生成的cl_事件来收集。根据您的建议,差距要小得多,而且非常小大约1%。
#include <boost/compute/container/mapped_view.hpp>
 #include <boost/compute/algorithm/transform.hpp>
 #include <boost/compute/functional/operator.hpp>
 #include <numeric>
 #include <algorithm>
 #include <functional>
 #include <boost/timer/timer.hpp>
 #include <boost/smart_ptr/scoped_array.hpp>
 #include <fstream>
 #include <boost/tuple/tuple_comparison.hpp>

 int main(){
     size_t const BUFFER_SIZE = 1UL << 13;
     boost::scoped_array<int> A(new int[BUFFER_SIZE]), B(new int[BUFFER_SIZE]), C(new int[BUFFER_SIZE]);

     std::iota(A.get(), A.get() + BUFFER_SIZE, 0);
     std::transform(A.get(), A.get() + BUFFER_SIZE, B.get(), std::bind(std::multiplies<int>(), std::placeholders::_1, 2));

     try{
         if (boost::compute::system::default_device().type() != CL_DEVICE_TYPE_GPU){
             std::cerr << "Not GPU\n";
         }
         else{
             boost::compute::command_queue queue = boost::compute::system::default_queue();
             boost::compute::mapped_view<int> mA(static_cast<const int*>(A.get()), BUFFER_SIZE),
                 mB(static_cast<const int*>(B.get()), BUFFER_SIZE);
             boost::compute::mapped_view<int> mC(C.get(), BUFFER_SIZE);
             {
                 boost::timer::auto_cpu_timer timer;
                 boost::compute::transform(
                     mA.cbegin(), mA.cend(),
                     mB.cbegin(),
                     mC.begin(),
                     boost::compute::plus<int>(),
                     queue
                     );
                 mC.map(CL_MAP_READ, queue);
             }
             std::ofstream gpu("gpu.txt");
             for (size_t i = 0; i != BUFFER_SIZE; ++i) gpu << C[i] << " ";
             mC.unmap(queue);
         }
     }
     catch (boost::compute::opencl_error const &err){
         std::cerr << err.what() << "\n";
     }

     return EXIT_SUCCESS;
 }