目录
前言
在《玩转 ArrayFire:11 计时函数》中,我们已经了解到 ArrayFire 的计时函数,在这一篇中,我们将继续学习 ArrayFire 的并行 for 循环:GFOR ,即在 GPU 或设备上同时运行多个独立的循环。
一、概述
GFOR 可以在 GPU 或设备上同时启动 for 循环的所有迭代,只要迭代是独立的。标准的 for 循环按顺序执行每个迭代,而 ArrayFire 的 gfor 循环则同时(并行地)执行每个迭代。ArrayFire 通过平铺所有循环迭代,然后在这些平铺上执行一次计算来实现这一点。
你可以把 GFOR 看作是对你的代码执行自动向量化,例如,你编写了一个 gfor 循环,对 vector 的每个元素递增,但在后台,ArrayFire 会重写它,以并行地对整个 vector 进行操作。
for (int i = 0; i < n; ++i)
A(i) = A(i) + 1;
gfor (seq i, n)
A(i) = A(i) + 1;
在后台,ArrayFire 会把你的代码改写成这个等价的、更快的版本:
A = A + 1;
注意:最好尽可能地向量化计算,以避免for循环和gfor循环中的开销。
再看另一个例子,你可以用 for 循环运行FFT,或者你也可以“向量化”,简单地在一个 gfor 循环操作中完成所有操作:
for (int i = 0; i < N; ++i)
A(span,span,i) = fft2(A(span,span,i)); // runs each FFT in sequence
gfor (seq i, N)
A(span,span,i) = fft2(A(span,span,i)); // runs N FFTs in parallel
实例化 gfor 循环有三种格式:
- gfor(var,n) :创建一个序列 {0,1,…, n - 1} ;
- gfor(var,first,last) :创建一个序列 {first, first+1, …, last};
- gfor(var,first,incr,last) :创建一个序列{first, first + inc, first + 2 * inc, …, last}
所以下面所有的代码都代表了等价序列{0, 1, 2, 3, 4}:
gfor (seq i, 5)
gfor (seq i, 0, 4)
gfor (seq i, 0, 1, 4)
有如下例子进行进一步说明:
array A = constant(1, n, n);
array B = constant(1, 1, n);
gfor (seq k, 0, n-1) {
B(span, k) = sum(A(span, k) * A(span,k)); // inner product
}
array A = randu(n,m);
array B = constant