私は新しい分野であるGPUで計算を実行するためにC++とcuda/thrustを使用しています。残念ながら、私のコード(以下のMCVE)は効率的ではありませんので、最適化する方法を知りたいと思います。コードは次の操作を実行します。Cuda Thrust - sort_by_key、merge_by_key、およびreduce_by_keyを使用してコードを最適化する方法
2つのキーベクトルと2つの値ベクトルがあります。キーベクトルは基本的に上三角行列のiとj(この例ではサイズ4x4)を含んでいます。
key1 {0, 0, 0, 1, 1, 2} value1: {0.5, 0.5, 0.5, -1.0, -1.0, 2.0}
key2 {1, 2, 3, 2, 3, 3} value2: {-1, 2.0, -3.5, 2.0, -3.5, -3.5}
タスクは、同じキーを持つすべての値を超える合計することです。これを達成するため、sort_by_keyを使用して2番目の値ベクトルをソートしました。結果は次のとおりです。
key1 {0, 0, 0, 1, 1, 2} value1: {0.5, 0.5, 0.5, -1.0, -1.0, 2.0}
key2 {1, 2, 2, 3, 3, 3} value2: {-1.0, 2.0, 2.0, -3.5, -3.5, -3.5}
はその後、私は以前よりも大きな二重サイズで、新しいキーと値のベクトルにつながるmerge_by_keyを使用して、両方の値ベクトルを、吸収合併しました。
key_merge {0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3}
value_merge {0.5, 0.5, 0.5, -1.0, -1.0, -1.0, 2.0, 2.0, 2.0, -3.5, -3.5, -3.5}
最後の手順では、reduce_by_keyを使用して、すべての値を同じキーで合計します。結果は次のとおりです。
key {0, 1, 2, 3} value: {1.5, -3.0, 6.0, -10.5}
この操作を実行し、それ以下のコードは、ゆっくりと静かで、私は大きいサイズのパフォーマンスが悪いことになることを恐れています。どのように最適化することができますか? sort_by_key、merge_by_key、reduce_by_keyを融合することは可能ですか?あらかじめsort_by_keyから結果のキーベクトルを知っているので、値ベクトルを「古いキーから新しいキーに」変換することは可能ですか?それらを減らす前に2つのベクトルをマージするのは理にかなっていますか?値/キーベクトルの各ペアに対してreduce_by_keyを別々に使用する方が速いのですか?事実を使用してreduce_by_key計算をスピードアップすることは可能ですか?ここでは異なるキー値の数が分かり、等価キーの数は常に同じですか?
#include <stdio.h>
#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/sort.h>
#include <thrust/reduce.h>
#include <thrust/merge.h>
int main(){
int key_1[6] = {0, 0, 0, 1, 1, 2};
int key_2[6] = {1, 2, 3, 2, 3, 3};
thrust::device_vector<double> k1(key_1,key_1+6);
thrust::device_vector<double> k2(key_2,key_2+6);
double value_1[6] = {0.5, 0.5, 0.5, -1.0, -1.0, 2.0};
double value_2[6] = {-1, 2.0, -3.5, 2.0, -3.5, -3.5};
thrust::device_vector<double> v1(value_1,value_1+6);
thrust::device_vector<double> v2(value_2,value_2+6);
thrust::device_vector<double> mk(12);
thrust::device_vector<double> mv(12);
thrust::device_vector<double> rk(4);
thrust::device_vector<double> rv(4);
thrust::sort_by_key(k2.begin(), k2.end(), v2.begin());
thrust::merge_by_key(k1.begin(), k1.end(), k2.begin(), k2.end(),v1.begin(), v2.begin(), mk.begin(), mv.begin());
thrust::reduce_by_key(mk.begin(), mk.end(), mv.begin(), rk.begin(), rv.begin());
for (unsigned i=0; i<4; i++) {
double tmp1 = rk[i];
double tmp2 = rv[i];
printf("key value %f is related to %f\n", tmp1, tmp2);
}
return 0;
}
結果:
key value 0.000000 is related to 1.500000
key value 1.000000 is related to -3.000000
key value 2.000000 is related to 6.000000
key value 3.000000 is related to -10.500000