Dies ist eine Reduzierung, viele Frameworks (wie kokkos und cuda) bieten Unterstützung für die Reduzierung von Skalaren, wobei aus jeder parallelisierten Berechnung eine Zahl summiert wird. Allerdings möchte ich eine Matrix reduzieren.
Die resultierende Matrix skaliert mit der Problemgröße, bleibt aber immer weitaus kleiner als die Anzahl der parallelisierten Berechnungen. Zu jedem Matrixeintrag gibt es immer mehrere Beiträge.
Mein Code ist in C++ und ich verwende derzeit das Kokkos-Framework, um die Parallelisierung zu erreichen.
Versuche
1
Ich habe versucht, jedem Thread eine Kopie der Matrix zu geben und alle diese vom Gerät (GPU) auf den Host (CPU) zu kopieren ) und seriell summieren.- Der GPU-Speicherbedarf für alle Matrizen bedeutete, dass ich die Berechnung in kleinen Mengen durchführen musste
- Das Kopieren von Daten vom Gerät zum Host war riesig und ineffizient, um es später zusammenzufassen
- Die Laufzeit war letztendlich langsamer als die serielle Methode
2
Wie oben, aber ich habe die serielle Summierung an einem durchgeführt Thread auf dem Gerät (GPU) kopierte dann die summierte Matrix auf den Host- Immer noch das gleiche GPU-Speicherlimit
- Die serielle Summierung in einem GPU-Thread war sehr langsam
- Minimale Speicherkopierzeit
- Die Laufzeit entsprach nahezu der seriellen Methode
3
Ich habe eine geräteseitige Matrix mit der Speichereigenschaft Kokkos::Atomic erstellt und dann jeden Thread + = sein Beitrag zur einen Matrix. Dies beruht auf dem Zugriff auf die atomare Matrix, um Kollisionen zu verhindern. Ich kopiere diese Matrix dann auf den Host.- Dies hat eine atomare Operation, die die Parallelisierung beeinträchtigt
- Minimale Speicherkopierzeit
- Insgesamt eine 20-fache Geschwindigkeitssteigerung, gut, aber weitaus schlechter als das theoretische Potenzial der GPU (A100 mit 10752). CUDA-Kerne).
- Das ist das Schema, mit dem ich fortfahren werde, wenn ich es nicht besser machen kann
Gibt es in C++ ein besseres Framework mit standardisierter Funktionalität?
Minimalbeispiel mit atomarer Matrix:
Code: Select all
#include
#include
int main(int argc, char *argv[]) {
Kokkos::initialize();
int matrix_size = 200;
int batches = 10;
Kokkos::View r("result_matrix", matrix_size,
matrix_size);
for (int batch = 0; batch < batches; batch++) {
Kokkos::parallel_for(
"populate", Kokkos::RangePolicy(0, 10752), KOKKOS_LAMBDA(const int i) {
//calculation goes here
//index and values should be calculated i dependent
r(42, 43) += 0.013;
r(42, 46) += 0.02;
});
}
auto h_r = Kokkos::create_mirror_view(r);
Kokkos::deep_copy(h_r, r);
std::cout