在《玩转 ArrayFire:06 矢量化介绍》中,我们已经了解到几种使用 ArrayFire 对代码进行向量化的方法,在这一篇中,我们将继续学习 ArrayFire 的数组和矩阵操作。
ArrayFire 提供了几种不同的操作数组和矩阵的方法。这些方法或函数包括如下几种:
函数名 | 含义 |
---|---|
moddims() | 在不改变数据的情况下改变数组的维数 |
array() | 创建不同维度数组的(浅)副本 |
flat() | 将数组平展为一维 |
flip() | 沿维度翻转数组 |
join() | 最多连接4个数组 |
reorder() | 更改数组中的维度顺序 |
shift() | 沿着维度移动数据 |
tile() | 沿维度重复数组 |
transpose() | 矩阵转置 |
T() | 矩阵或向量的转置(简写) |
H() | 厄米矩阵的转置(共轭转置) |
下面我们将提供这些函数的几个示例及其用法。
该函数的作用是将数组简化为一维:
a [3 3 1 1]
1.0000 4.0000 7.0000
2.0000 5.0000 8.0000
3.0000 6.0000 9.0000
flat(a) [9 1 1 1]
1.0000
2.0000
3.0000
4.0000
5.0000
6.0000
7.0000
8.0000
9.0000
flat() 函数可以在 C++ 中调用,如下所示:
array af::flat(const array& in) – C++ interface for flat() function
该函数的作用是沿着选定的维度翻转数组的内容。在下面的例子中,我们展示了 5x2 数组沿着第 0 和第 1 轴翻转:
a [5 2 1 1]
1.0000 6.0000
2.0000 7.0000
3.0000 8.0000
4.0000 9.0000
5.0000 10.0000
flip(a, 0) [5 2 1 1]
5.0000 10.0000
4.0000 9.0000
3.0000 8.0000
2.0000 7.0000
1.0000 6.0000
flip(a, 1) [5 2 1 1]
6.0000 1.0000
7.0000 2.0000
8.0000 3.0000
9.0000 4.0000
10.0000 5.0000
flip() 函数可以在 C++ 中调用,如下所示:
array af::flip(const array &in, const unsigned dim) – C++ interface for flip()
该函数的作用是沿着特定的维度连接数组。C++ 最多可以连接 4 个数组,而 C 最多支持 10 个数组。下面是一个如何将数组连接到自身的例子:
a [5 1 1 1]
1.0000
2.0000
3.0000
4.0000
5.0000
join(0, a, a) [10 1 1 1]
1.0000
2.0000
3.0000
4.0000
5.0000
1.0000
2.0000
3.0000
4.0000
5.0000
join(1, a, a) [5 2 1 1]
1.0000 1.0000
2.0000 2.0000
3.0000 3.0000
4.0000 4.0000
5.0000 5.0000
join() 函数在 C++ 语言中有几个候选函数:
array af::join(const int dim, const array &first, const array &second) – Joins 2 arrays along a dimension
array af::join(const int dim, const array &first, const array &second, const array &third) – Joins 3 arrays along a dimension.
array af::join(const int dim, const array &first, const array &second, const array &third, const array &fourth) – Joins 4 arrays along a dimension
该函数的作用是改变数组的维度,但不改变数组的数据或顺序。注意,这个函数只修改与数组相关联的元数据。它不修改数组的内容。下面是一个将8x1数组转换为2x4,然后再返回8x1的例子:
a [8 1 1 1]
1.0000
2.0000
1.0000
2.0000
1.0000
2.0000
1.0000
2.0000
af::dim4 new_dims(2, 4);
moddims(a, new_dims) [2 4 1 1]
1.0000 1.0000 1.0000 1.0000
2.0000 2.0000 2.0000 2.0000
moddims(a, a.elements(), 1, 1, 1) [8 1 1 1]
1.0000
2.0000
1.0000
2.0000
1.0000
2.0000
1.0000
2.0000
moddims() 函数在 C++ API 中有几个候选函数:
array af::moddims(const array &in, const unsigned ndims, const dim_t *const dims) – mods number of dimensions to match ndims as specidied in the array dims
array af::moddims(const array &in, const dim4 &dims) – mods dimensions as specified by dims
array af::moddims(const array &in, const dim_t d0, const dim_t d1=1, const dim_t d2=1, const dim_t d3=1) – mods dimensions of an array
该函数的作用是根据维度的变化交换数据,从而修改数组中数据的顺序。数组内的数据保持线性顺序。
a [2 2 3 1]
1.0000 3.0000
2.0000 4.0000
1.0000 3.0000
2.0000 4.0000
1.0000 3.0000
2.0000 4.0000
reorder(a, 1, 0, 2) [2 2 3 1] //equivalent to a transpose
1.0000 2.0000
3.0000 4.0000
1.0000 2.0000
3.0000 4.0000
1.0000 2.0000
3.0000 4.0000
reorder(a, 2, 0, 1) [3 2 2 1]
1.0000 2.0000
1.0000 2.0000
1.0000 2.0000
3.0000 4.0000
3.0000 4.0000
3.0000 4.0000
reorder() 函数在 C++ API 中有几个候选函数:
array af::reorder(const array &in, const unsigned x, const unsigned y=1, const unsigned z=2, const unsigned w=3) – Reorders dimensions of an array
该函数的作用是沿着选定的维度以循环缓冲区的方式移动数据。考虑以下示例:
a [3 5 1 1]
0.0000 0.0000 0.0000 0.0000 0.0000
3.0000 4.0000 5.0000 1.0000 2.0000
3.0000 4.0000 5.0000 1.0000 2.0000
shift(a, 0, 2 ) [3 5 1 1]
0.0000 0.0000 0.0000 0.0000 0.0000
1.0000 2.0000 3.0000 4.0000 5.0000
1.0000 2.0000 3.0000 4.0000 5.0000
shift(a, -1, 2 ) [3 5 1 1]
1.0000 2.0000 3.0000 4.0000 5.0000
1.0000 2.0000 3.0000 4.0000 5.0000
0.0000 0.0000 0.0000 0.0000 0.0000
shift() 函数可以在 C++ 中调用,如下所示:
array af::shift(const array &in, const int x, const int y=0, const int z=0, const int w=0) – Shifts array along specified dimensions
该函数的作用是沿着指定的维度重复一个数组。下面的例子展示了如何重复数组的第 0 维和第 1 维:
a [3 1 1 1]
1.0000
2.0000
3.0000
// Repeat array a twice in the zeroth dimension
tile(a, 2) [6 1 1 1]
1.0000
2.0000
3.0000
1.0000
2.0000
3.0000
// Repeat array a twice along both the zeroth and first dimensions
tile(a, 2, 2) [6 2 1 1]
1.0000 1.0000
2.0000 2.0000
3.0000 3.0000
1.0000 1.0000
2.0000 2.0000
3.0000 3.0000
// Repeat array a twice along the first and three times along the second
// dimension.
af::dim4 tile_dims(1, 2, 3);
tile(a, tile_dims) [3 2 3 1]
1.0000 1.0000
2.0000 2.0000
3.0000 3.0000
1.0000 1.0000
2.0000 2.0000
3.0000 3.0000
1.0000 1.0000
2.0000 2.0000
3.0000 3.0000
tile() 函数可以在 C++ 中调用,如下所示:
array af::tile(const array &in, const unsigned x, const unsigned y=1, const unsigned z=1, const unsigned w=1) – Tiles array along specified dimensions
array af::tile(const array &in, const dim4 &dims) – Tile an array according to a dim4 object
该函数的作用是执行一个标准的矩阵转置。输入数组必须具有 2D 矩阵的维数。
a [3 3 1 1]
1.0000 3.0000 3.0000
2.0000 1.0000 3.0000
2.0000 2.0000 1.0000
transpose(a) [3 3 1 1]
1.0000 2.0000 2.0000
3.0000 1.0000 2.0000
3.0000 3.0000 1.0000
transpose() 函数可以在 C++ 中调用,如下所示:
array af::transpose(const array &in, const bool conjugate=false) – Transposes a matrix.
void af::transposeInPlace(array &in, const bool conjugate=false) – Transposes a matrix in-place.
__array af::T() – Transpose a matrix
__array af::H() – Conjugate Transpose (Hermitian transpose) of a matrix
下面是一个如何使用简写版本的例子:
array x = randu(2, 2, f32);
af_print(x.T()); // transpose (real)
array c = randu(2, 2, c32);
af_print(c.T()); // transpose (complex)
af_print(c.H()); // Hermitian (conjugate) transpose
该函数可用于创建不同尺寸矩阵的(浅)副本。元素的总数必须保持不变。这个函数是前面讨论的moddim()函数的包装。
通过使用数组重组函数的组合,可以用几行代码快速编写复杂的操作模式。例如,考虑为网格生成 (x,y) 坐标,其中每个轴从 1 到 n 。我们可以使用上述函数的一个小组合,而不是使用几个循环来填充数组。
unsigned n=3;
af::array xy = join(1,
tile(seq(1, n), n),
flat( transpose(tile(seq(1, n), 1, n)) )
);
xy [9 2 1 1]
1.0000 1.0000
2.0000 1.0000
3.0000 1.0000
1.0000 2.0000
2.0000 2.0000
3.0000 2.0000
1.0000 3.0000
2.0000 3.0000
3.0000 3.0000