前言
目前,程序员和数据科学家希望利用快速并行计算设备的优势。为了从当前的并行硬件和科学计算软件中获得最佳性能,有必要使用向量化代码。然而,编写向量化代码可能不是立即直观的。ArrayFire 提供了许多向量化给定代码段的方法。在本篇中,我们将介绍几种使用 ArrayFire 对代码进行向量化的方法,并讨论每种方法的优缺点。
一、通用/默认矢量化
就其本质而言,ArrayFire 是一个矢量化库。大多数函数对 array 进行整体操作——对所有元素进行并行操作。只要可能,应该使用现有的矢量化函数,而不是手工索引到数组中。例如,考虑下面的代码:
af::array a = af::range(10); // [0, 9]
for(int i = 0; i < a.dims(0); ++i)
{
a(i) = a(i) + 1; // [1, 10]
}
尽管代码完全有效,但效率非常低,因为它导致内核只对一个数据进行操作。相反,开发人员应该使用 ArrayFire 的 + 操作符重载:
af::array a = af::range(10); // [0, 9]
a = a + 1; // [1, 10]
这段代码将导致一个内核并行地操作 a 的所有 10 个元素。
大多数 ArrayFire 函数都是矢量化的。其中的一小部分包括:
操作符类型 | 函数 |
---|---|
算术运算 | +, -, *, /, %, >>, << |
逻辑运算 | &&, ||, <, >, ==, != |
数值函数 | abs(), floor(), round(), min(), max() |
复数运算 | real(), imag(), conj() |
指数和对数函数 | exp(), log(), expm1(), log1p() |
三角函数 | sin(), cos(), tan() |
双曲函数 | sinh(), cosh(), tanh() |
除了元素操作之外,许多其他函数也在 ArrayFire 中矢量化。
请注意,即使执行某种形式的聚合(如 sum() 或 min() )、信号处理(如 convolve() )、甚至图像处理函数(如 rotate() ),ArrayFire 都支持对不同的列或图像进行矢量化。例如,如果我们有宽为WIDTH、高为HEIGHT的NUM个图像,我们可以用如下向量方式卷积每个图像:
float g_coef[] = {
1, 2, 1,