本記事では、CUDAのThrustライブラリを用いて、GPU側にある2つの配列同士の各要素を四則演算する方法や、GPU側にある1つの配列の対して、正負を逆転させる方法を紹介します。
ちなみに、配列同士ではなく、配列の全ての要素の総和を求める方法は以下の記事で紹介しています。
ThrustはCUDA C++のテンプレートライブラリで、CUDAをインストールすると自動的に付いてくるライブラリです。
これはC++のSTL(Standard Template Library)と呼ばれるC++の開発でよく使われる標準ライブラリと似た文法で書けることが特徴で、通常のCUDAのプログラミングと比較すると、CPUからGPU側へのデータの転送などを簡易な文法で実現することができます。
よってThrustを使うことで、C++に慣れている人にとっては比較的少ない労力でCUDAを用いたGPUプログラミングをすることができます。
一方、実装されているny処理には限りがあり、何でもできるわけではありません。Thrustに実装されている機能の例としては、配列の総和を求めたり、配列をソートしたりする機能が挙げられます。
以下に、GPU側で2つの配列同士で四則演算を行うプログラムを紹介します。入力としてXとYという二つの配列を用意します。Zは出力用の配列です。
#include <iostream>
#include <thrust/device_vector.h>
#include <thrust/transform.h>
int main()
{
// Creating device vectors
thrust::device_vector<float> X(5);
thrust::device_vector<float> Y(5);
thrust::device_vector<float> Z(5);
for (int i = 0; i < 5; i++) {
X[i] = 2 * i; // X = {0, 2, 4, 6, 8}
Y[i] = -i; // Y = {0,-1,-2,-3,-4}
}
std::cout << std::endl;
// Confirmation (Input)
std::cout << "X : " << X[0] << " " << X[1] << " " << X[2] << " " << X[3] << " " << X[4] << std::endl;
std::cout << "Y : " << Y[0] << " " << Y[1] << " " << Y[2] << " " << Y[3] << " " << Y[4] << std::endl;
thrust::transform(X.begin(), X.end(), Z.begin(), thrust::negate<float>());
std::cout << "Z = -X: " << std::endl << " " << Z[0] << " " << Z[1] << " " << Z[2] << " " << Z[3] << " " << Z[4] << std::endl;
thrust::transform(X.begin(), X.end(), Y.begin(), Z.begin(), thrust::plus<float>());
std::cout << "Z = X + Y: " << std::endl << " " << Z[0] << " " << Z[1] << " " << Z[2] << " " << Z[3] << " " << Z[4] << std::endl;
thrust::transform(X.begin(), X.end(), Y.begin(), Z.begin(), thrust::minus<float>());
std::cout << "Z = X - Y: " << std::endl << " " << Z[0] << " " << Z[1] << " " << Z[2] << " " << Z[3] << " " << Z[4] << std::endl;
thrust::transform(X.begin(), X.end(), Y.begin(), Z.begin(), thrust::multiplies<float>());
std::cout << "Z = X * Y: " << std::endl << " " << Z[0] << " " << Z[1] << " " << Z[2] << " " << Z[3] << " " << Z[4] << std::endl;
thrust::transform(X.begin(), X.end(), Y.begin(), Z.begin(), thrust::divides<float>());
std::cout << "Z = X / Y: " << std::endl << " " << Z[0] << " " << Z[1] << " " << Z[2] << " " << Z[3] << " " << Z[4] << std::endl;
return 0;
}
実行すると、以下の結果が得られます。
以下のコードで、Xの要素の正負を逆転させてZに出力することができます。
thrust::transform(X.begin(), X.end(), Z.begin(), thrust::negate<float>());
以下のコードで、XとYの各要素の和をZに出力することができます。
thrust::transform(X.begin(), X.end(), Y.begin(), Z.begin(), thrust::plus<float>());
以下のコードで、XとYの各要素の差(X-Y)をZに出力することができます。
thrust::transform(X.begin(), X.end(), Y.begin(), Z.begin(), thrust::minus<float>());
以下のコードで、XとYの各要素の積(X×Y)をZに出力することができます。
thrust::transform(X.begin(), X.end(), Y.begin(), Z.begin(), thrust::multiplies<float>());
以下のコードで、XとYの各要素の商(X/Y)をZに出力することができます。
thrust::transform(X.begin(), X.end(), Y.begin(), Z.begin(), thrust::divides<float>());