使用Boost::Compute传递两值到自定义函数时遇编译错误求助
Boost::Compute双向量元素乘积计算编译错误解决
我在Windows 10 + Visual Studio 2022环境下,通过vcpkg安装了OpenCL和Boost::Compute,想要用Boost::Compute实现两个向量元素的乘积计算,但编译时出现错误。
代码实现
#include <random> #include <vector> #include <boost/compute/core.hpp> #include <boost/compute/lambda.hpp> #include <boost/compute/algorithm/transform.hpp> #include <boost/compute/container/vector.hpp> std::mt19937 rng{ std::random_device()() }; std::uniform_int_distribution<> dist(1); namespace compute = boost::compute; using namespace boost::compute::lambda; int GetRandomNumber() { return dist(rng); } int main(int argc, char* argv[]) { const auto device = compute::system::default_device(); const compute::context context(device); compute::command_queue commandQueue(context, device); std::vector<int> hostVector1(10000); std::vector<int> hostVector2(10000); std::vector<int> hostResultVector(10000); std::ranges::generate(hostVector1, GetRandomNumber); std::ranges::generate(hostVector2, GetRandomNumber); compute::vector<int> deviceVector1(hostVector1.size(), context); compute::vector<int> deviceVector2(hostVector2.size(), context); compute::vector<int> deviceResultVector(hostResultVector.size(), context); compute::copy(hostVector1.begin(), hostVector1.end(), deviceVector1.begin(), commandQueue); compute::copy(hostVector2.begin(), hostVector2.end(), deviceVector2.begin(), commandQueue); transform(deviceVector1.begin(), deviceVector1.end(), deviceVector2.begin(), deviceResultVector.begin(), _1 * _2, commandQueue); compute::copy(deviceResultVector.begin(), deviceResultVector.end(), hostResultVector.begin(), commandQueue); return 0; }
编译错误信息
1>C:\Users\Dave\source\repos\BoostComputeTest\BoostComputeTest\vcpkg_installed\x64-windows\x64-windows\include\boost\compute\iterator\transform_iterator.hpp(177,53): error C2039: 'get_buffer': is not a member of 'boost::compute::zip_iterator<boost::tuples::tuple<boost::compute::buffer_iterator<T>,boost::compute::buffer_iterator<T>,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type,boost::tuples::null_type>>' 1>C:\Users\Dave\source\repos\BoostComputeTest\BoostComputeTest\vcpkg_installed\x64-windows\x64-windows\include\boost\compute\iterator\transform_iterator.hpp(177,53): error C2039: with 1>C:\Users\Dave\source\repos\BoostComputeTest\BoostComputeTest\vcpkg_installed\x64-windows\x64-windows\include\boost\compute\iterator\transform_iterator.hpp(177,53): error C2039: [ 1>C:\Users\Dave\source\repos\BoostComputeTest\BoostComputeTest\vcpkg_installed\x64-windows\x64-windows\include\boost\compute\iterator\transform_iterator.hpp(177,53): error C2039: T=int 1>C:\Users\Dave\source\repos\BoostComputeTest\BoostComputeTest\vcpkg_installed\x64-windows\x64-windows\include\boost\compute\iterator\transform_iterator.hpp(177,53): error C2039: ] 1>(compiling source file 'Main.cpp') 1> C:\Users\Dave\source\repos\BoostComputeTest\BoostComputeTest\vcpkg_installed\x64-windows\x64-windows\include\boost\compute\iterator\zip_iterator.hpp(172,7):
问题分析与解决
这个错误属于Boost::Compute库内部的接口兼容性问题:当使用双输入参数的transform算法时,库内部会生成zip_iterator来封装两个输入迭代器,但该迭代器并未实现get_buffer方法,导致编译失败。你可以通过以下两种方式解决当前问题,同时也可以向Boost项目提交bug报告修复该底层问题。
改用
for_each配合zip_iterator实现
替换原代码中的transform调用:compute::for_each( compute::make_zip_iterator(boost::make_tuple(deviceVector1.begin(), deviceVector2.begin())), compute::make_zip_iterator(boost::make_tuple(deviceVector1.end(), deviceVector2.end())), (_1[0] * _1[1]) >> deviceResultVector.begin()[_index], commandQueue );使用自定义OpenCL内核实现
直接编写内核代码执行元素乘积:const char multiply_kernel[] = R"( __kernel void multiply(__global const int* a, __global const int* b, __global int* result) { int i = get_global_id(0); result[i] = a[i] * b[i]; } )"; compute::program program = compute::program::create_with_source(multiply_kernel, context); program.build(); compute::kernel kernel(program, "multiply"); kernel.set_arg(0, deviceVector1.get_buffer()); kernel.set_arg(1, deviceVector2.get_buffer()); kernel.set_arg(2, deviceResultVector.get_buffer()); commandQueue.enqueue_1d_range_kernel(kernel, 0, deviceVector1.size(), 0);
内容的提问来源于stack exchange,提问作者Dave F
相关产品推荐
相关产品推荐

