C++ 中的元素操作

Posted

技术标签:

【中文标题】C++ 中的元素操作【英文标题】:Element-wise operations in C++ 【发布时间】:2013-12-08 18:49:06 【问题描述】:

是否有一个预先存在的库可以让我创建具有以下属性的类似数组的对象:

    运行时大小规范(在实例化时选择,之后不会增长或缩小) 重载操作符以执行元素操作(即c=a+b 将产生一个向量cc[i]=a[i]+b[i] 用于所有i,类似地用于*-/ 等) 一组很好的按元素作用的函数,例如x=sqrt(vec) 将有元素x[i]=sqrt(vec[i]) 提供“总结”功能,如sum(vec)mean(vec)等 (可选)可以将操作发送到 GPU 进行处理。

基本上类似于 Fortran 中数组的工作方式,隐藏了所有实现。目前我正在使用 STL 中的vector 并手动重载运算符,但我觉得这可能是一个已解决的问题。

【问题讨论】:

或许你可以试试Eigen library。 【参考方案1】:

在标准库的尘土飞扬的角落,早已被大家遗忘,有一个名为valarray 的类。查找它,看看它是否适合您的需求。

来自manual page at cppreference.com:

std::valarray 是用于表示和操作值数组的类。它支持逐元素数学运算和各种形式的广义下标运算符、切片和间接访问。

用于说明的代码sn-p:

#include <valarray>
#include <algorithm>
#include <iterator>
#include <iostream>

int main()

    std::valarray<int> a  1, 2, 3, 4, 5;
    std::valarray<int> b = a;
    std::valarray<int> c = a + b;
    std::copy(begin(c), end(c),
        std::ostream_iterator<int>(std::cout, " "));

输出:2 4 6 8 10

【讨论】:

【参考方案2】:

您可以使用 Cilk Plus Extentions (https://www.cilkplus.org/),它通过对 C/C++ 中相同形状的数组应用逐元素操作来提供数组表示法。它探索了处理器和协处理器的向量并行性。

示例: 标准 C 代码:

for (i=0; i<MAX; i++)
   c[i]=a[i]+b[i];

Cilk Plus - 数组表示法:

c[i:MAX]=a[i:MAX]+b[i:MAX];

跨步部分,例如:

float d[10] = 0,1,2,3,4,5,6,7,8,9;
float x[3];
x[:] = d[0:3:2]; //x contains 0,2,4 values

您可以对数组部分使用归约:

_sec_reduce_add(a[0:n]);

兴趣阅读: http://software.intel.com/en-us/articles/getting-started-with-intel-cilk-plus-array-notations

【讨论】:

【参考方案3】:

作为 CUDA 工具包的一部分的 Thrust 库为 GPU 上的矢量运算提供了一个类似 STL 的接口。它也有一个 OpenMP 后端,但是 GPU 支持利用了 CUDA,因此您只能使用 NVIDIA GPU。如果您想让像 c=a+b 这样的表达式适用于向量,您将不得不自己进行包装(比如使用表达式模板)

https://code.google.com/p/thrust/

VienaCL 库采用更高级的方法,提供您想要的向量和矩阵运算。它同时具有 CUDA 和 OpenCL 后端,因此您可以使用来自不同供应商的 GPU(和多核 CPU)。

http://viennacl.sourceforge.net/

vexcl 库看起来也很有前途(同样支持 OpenCL 和 CUDA)

https://github.com/ddemidov/vexcl

【讨论】:

以上是关于C++ 中的元素操作的主要内容,如果未能解决你的问题,请参考以下文章

[C++ STL] set使用详解

C++ STL list详解

对 Vector 元素的 push_back 操作 (C++)

如何清除向量中的所有元素,除了C++中向量中的最后一个元素

C++顺序容器知识总结

C++迭代器的使用和操作总结