Ich verwende C++ und Cuda/Schub, um eine Berechnung auf der GPU durchzuführen, die ein neues Feld für mich ist. Leider ist mein Code (MCVE unten) nicht sehr effizient, daher würde ich gerne wissen, wie ich ihn optimieren kann. Der Code führt die folgenden Operationen aus:Cuda Thrust - So optimieren Sie einen Code mit sort_by_key, merge_by_key und reduce_by_key
Es gibt zwei Schlüsselvektor und zwei Wertvektor. Die Schlüsselvektoren enthalten grundsätzlich die i und j einer oberen Dreiecksmatrix (in diesem Beispiel: der Größe 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}
Die Aufgabe ist die Summe aller Werte, die denselben Schlüssel haben. Um das zu erreichen, sortierte ich den zweiten Wertvektor mit sort_by_key. Das Ergebnis ist:
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}
Danach habe ich fusionierte beide Wertvektor merge_by_key verwenden, die mit einer Größe doppelt so groß zu einem neuen Schlüssel und Wertvektor führt als zuvor.
Der letzte Schritt ist die Verwendung von reduce_by_key, um alle Werte mit demselben Schlüssel zu summieren. Das Ergebnis ist:
key {0, 1, 2, 3} value: {1.5, -3.0, 6.0, -10.5}
Der Code unterhalb derer führen diese Operationen ruhig ist langsam, und ich fürchte, dass die Leistung für größere Größe schlecht sein wird. Wie kann es optimiert werden? Ist es möglich, sort_by_key, merge_by_key und reduce_by_key zu fusionieren? Da ich den resultierenden Schlüsselvektor aus sort_by_key im Voraus kenne, ist es möglich, den Wertvektor "von einem alten zu einem neuen Schlüssel" zu transformieren? Macht es Sinn, zwei Vektoren zusammenzufassen, bevor sie reduziert werden, oder ist es schneller, reduce_by_key separat für jedes Paar von Wert/Schlüsselvektor zu verwenden? Ist es möglich, die reduce_by_key-Berechnung zu beschleunigen, indem man die Tatsache nutzt, dass hier die Anzahl der verschiedenen Schlüsselwerte bekannt ist und die Anzahl der gleichen Schlüssel immer gleich ist?
#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;
}
Ergebnis:
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