Boost.Compute或GPU / CPU并行计算。第1部分

介绍



哈Ha!



按照我的标准,我已经写了很长时间的C ++代码,但是直到那时我还没有遇到与并行计算有关的任务。我还没有看过有关Boost.Compute库的文章,因此本文将对此进行介绍。

所有部分





内容



  • 什么是boost.compute
  • 将boost.compute连接到项目时出现问题
  • boost.compute简介
  • 基本计算类别
  • 入门
  • 结论


什么是boost.compute



这个c ++库提供了一个简单的高级接口,用于与多核CPU和GPU计算设备进行交互。此库最初是在1.61.0版中添加的,以增强功能,但仍受支持。



将boost.compute连接到项目时出现问题



因此,在使用该库时遇到了一些问题。其中之一是,如果没有OpenCL,该库就无法正常工作。编译器给出以下错误:



图片



连接后,所有内容均应正确编译。



可以使用boost库下载它,并使用NuGet程序包管理器将其下载并连接到Visual Studio项目。



boost.compute简介



安装所有必需的组件之后,您可以查看简单的代码段。为了正确操作,以这种方式启用计算模块就足够了:



#include <boost/compute.hpp>
using namespace boost;


值得注意的是,常规stl容器不适合在计算名称空间算法中使用。而是有一些特殊创建的容器,它们与标准容器没有冲突。样例代码:



std::vector<float> std_vector(10);
compute::vector<float> compute_vector(std_vector.begin(), std_vector.end(), queue); 
//       ,     .


您可以使用copy()函数将其转换回std :: vector:



compute::copy(compute_vector.begin(), compute_vector.end(), std_vector.begin(), queue);


基本计算类别



该库包括三个辅助类,足以在视频卡和/或处理器上进行计算:



  • 计算::设备(将确定我们将使用的设备)
  • 计算::上下文(此类的对象存储OpenCL资源,包括内存缓冲区和其他对象)
  • compute :: command_queue(提供用于与计算设备进行交互的接口)


您可以这样声明整个事情:



auto device = compute::system::default_device(); //     
auto context = compute::context::context(device); //   
auto queue = compute::command_queue(context, device); //   


即使只使用上面的第一行代码,您也可以通过运行以下代码来确保一切正常运行:



std::cout << device.name() << std::endl; 


因此,我们获得了将在其上进行计算的设备的名称。结果(您可能会有所不同):



图片



入门



让我们来看一下trasform()和reduce()函数:



std::vector<float> host_vec = {1, 4, 9};

compute::vector<float> com_vec(host_vec.begin(), host_vec.end(), queue);
//           
//  copy()

compute::vector<float> buff_result(host_vec.size(), context);
transform(com_vec.begin(), com_vec.end(), buff_result.begin(), compute::sqrt<float>(), queue);

std::vector<float> transform_result(host_vec.size());
compute::copy(buff_result.begin(), buff_result.end(), transform_result.begin(), queue);
	
cout << "Transforming result: ";
for (size_t i = 0; i < transform_result.size(); i++)
{
	cout << transform_result[i] << " ";
}
cout << endl;

float reduce_result;
compute::reduce(com_vec.begin(), com_vec.end(), &reduce_result, compute::plus<float>(),queue);

cout << "Reducing result: " << reduce_result << endl;


当您运行上述代码时,您应该看到以下结果:



图片



我选择了这两种方法,因为它们很好地展示了并行计算的原始工作,而没有多余的东西。



因此,transform()函数用于通过将一个函数应用于所有值来更改数据数组(或两个数组,如果我们要传递它们的话)。



transform(com_vec.begin(), 
   com_vec.end(), 
   buff_result.begin(), 
   compute::sqrt<float>(), 
   queue);


让我们继续解析参数,前两个参数传递一个输入数据向量,第三个参数传递一个指向向量开始处的指针,将结果写入其中,下一个参数指示我们需要做的事情。在上面的示例中,我们使用标准矢量处理功能之一,即提取平方根。当然,您可以编写一个自定义函数,boost为我们提供了两种完整的方法,但这已经是下一部分的材料(如果有的话)。好吧,作为最后一个参数,我们传递了我上面提到的compute :: command_queue类的对象。



下一个函数是reduce(),这里的所有内容都更加有趣。此方法返回将第四个参数应用于向量的所有元素的结果。



compute::reduce(com_vec.begin(), 
   com_vec.end(), 
   &reduce_result, 
   compute::plus<float>(),
   queue);


现在,我将通过一个示例进行说明,可以将上面的代码与以下等式进行比较:

1+4+9

在我们的例子中,我们得到了数组中所有元素的总和。



结论



好,仅此而已,我认为这足以对大数据进行简单的操作。现在,您可以使用boost.compute库的原始功能,并且还可以防止在使用该库时出现一些错误。



我很高兴收到积极的反馈。感谢您的时间。



祝你们好运!



All Articles