Categories: CUDA

CUDA Thrustライブラリを用いて、配列同士の四則演算を行う方法

本記事では、CUDAのThrustライブラリを用いて、GPU側にある2つの配列同士の各要素を四則演算する方法や、GPU側にある1つの配列の対して、正負を逆転させる方法を紹介します。

ちなみに、配列同士ではなく、配列の全ての要素の総和を求める方法は以下の記事で紹介しています。

本記事では、CUDAのThrustのリダクション(reduction)計算の機能を用いて、GPU側で配列の総和を求める方法を紹介します。 ...

CUDA Thrustについて

ThrustはCUDA C++のテンプレートライブラリで、CUDAをインストールすると自動的に付いてくるライブラリです。

これはC++のSTL(Standard Template Library)と呼ばれるC++の開発でよく使われる標準ライブラリと似た文法で書けることが特徴で、通常のCUDAのプログラミングと比較すると、CPUからGPU側へのデータの転送などを簡易な文法で実現することができます。

よってThrustを使うことで、C++に慣れている人にとっては比較的少ない労力でCUDAを用いたGPUプログラミングをすることができます。

一方、実装されているny処理には限りがあり、何でもできるわけではありません。Thrustに実装されている機能の例としては、配列の総和を求めたり、配列をソートしたりする機能が挙げられます。

CUDA Thrustを用いて2つの配列同士で四則演算を行うプログラム

以下に、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>());

2つの配列の、各要素の和を計算する関数

以下のコードで、XとYの各要素の和をZに出力することができます。

thrust::transform(X.begin(), X.end(), Y.begin(), Z.begin(), thrust::plus<float>());

2つの配列の、各要素の差を計算する関数

以下のコードで、XとYの各要素の差(X-Y)をZに出力することができます。

thrust::transform(X.begin(), X.end(), Y.begin(), Z.begin(), thrust::minus<float>());

2つの配列の、各要素の積を計算する関数

以下のコードで、XとYの各要素の積(X×Y)をZに出力することができます。

thrust::transform(X.begin(), X.end(), Y.begin(), Z.begin(), thrust::multiplies<float>());

2つの配列の、各要素の商を計算する関数

以下のコードで、XとYの各要素の商(X/Y)をZに出力することができます。

thrust::transform(X.begin(), X.end(), Y.begin(), Z.begin(), thrust::divides<float>());
Haruoka