In dieser Artikelserie geht es um die parallele Programmierung mit MPI .
Teil 1. MPI - Einführung und das erste Programm.
Teil 2. MPI - Lernen, Prozesse zu überwachen.
Im vorherigen Artikel haben wir erläutert, wie ein Programm ausgeführt wird, was MPI ist und warum diese parallele Programmierung erforderlich ist, wenn Sie ohne sie schreiben können. In diesem Artikel gehen wir davon aus, dass der Leser das im vorherigen Artikel vorgestellte Material gelesen hat, und fahren mit dem nächsten Schritt zur Untersuchung der MPI- Technologie fort , nämlich der Prozesssteuerung. Um die Empörung erfahrener Programmierer zu vermeiden, meine ich weiter "Threads", "Prozesse" usw. Ein Teil eines Computersystems, auf dem eine bestimmte Instanz eines Programms ausgeführt wird (Dieser Teil kann entweder ein bestimmter Thread oder ein beliebiger Rechenknoten des Systems sein).
Prozessnummern und Gesamtzahl der Prozesse
Um beim Erstellen eines parallelen Programms nützliche Aktionen auszuführen, müssen Rollen zwischen Rechenknoten und Threads verteilt werden. Um dies zu tun, ist es für uns einfach wichtig zu wissen, welcher Thread eine bestimmte Instanz des darauf laufenden Programms verarbeitet, aber zunächst wäre es schön zu wissen, wie viele von ihnen überhaupt ausgeführt werden.
Um herauszufinden, auf welchem Thread das Programm ausgeführt wird, gibt es Prozeduren MPI_Comm_size . Es akzeptiert einen Kommunikator als Eingabe (wir werden später darüber sprechen) und die Speicheradresse, an die eine Ganzzahl geschrieben wird, dh die Anzahl der Threads , die das Programm verarbeiten.
int MPI_Comm_size(MPI_Comm comm, int* size)
? , , . , , . MPI , MPI_COMM_WORLD. , , .
, . MPI_Comm_size. , . :
int MPI_comm_rank(MPI_Comm comm, int* rank)
.
2 , , .
#include <stdio.h>
#include "mpi.h"
int main(int argc, char **argv)
{
int rank, size;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Finalize();
printf("Process: %d, size: %d\n", rank, size);
return 0;
}
5 :
Process: 0, size: 5
Process: 1, size: 5
Process: 2, size: 5
Process: 3, size: 5
Process: 4, size: 5
.
? , . , , , , .. , .
Comm_size, Comm_rank
. .
#include <stdio.h>
#include "mpi.h"
int main(int argc, char **argv)
{
const int MAX = 20;
int rank, size;
int n, ibeg, iend;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &size);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
n = (MAX - 1) / size + 1;
ibeg = rank * n + 1;
iend = (rank + 1) * n;
for(int i = ibeg; i <= ((iend > MAX) ? MAX : iend); i++)
{
printf("Process: %d, %d^2=%d\n", rank, i, i*i);
}
MPI_Finalize();
return 0;
}
5 :
Process: 0, 1^2=1
Process: 0, 2^2=4
Process: 0, 3^2=9
Process: 0, 4^2=16
Process: 1, 5^2=25
Process: 1, 6^2=36
Process: 1, 7^2=49
Process: 1, 8^2=64
Process: 2, 9^2=81
Process: 2, 10^2=100
Process: 2, 11^2=121
Process: 2, 12^2=144
Process: 3, 13^2=169
Process: 3, 14^2=196
Process: 3, 15^2=225
Process: 3, 16^2=256
Process: 4, 17^2=289
Process: 4, 18^2=324
Process: 4, 19^2=361
Process: 4, 20^2=400
MAX=20. , , .
, , , : . MPI , , .
, , , - . , , . MPI_Init, , , , - , . .
. MPI <time>, .
double MPI_Wtime(void);
double MPI_Wtick(void);
, . , , . , Wtime , .
, MPI_WTIME_IS_GLOBAL, 0 1, .
.
. MPI_Get_processor_name. :
int MPI_Get_Processor_name(char* name, int* len);
.
MPI, . .
Um das Wissen zu festigen, schlage ich vor, dass Sie ein einfaches Programm schreiben, das erkennt, ob eine Zahl für die Zahlen in einem vorgegebenen Bereich von 1 bis N eine Primzahl ist . Dies zeigt Ihnen deutlich, wie einfach und unkompliziert es ist, Berechnungen mit dieser Technologie zu parallelisieren, und ermöglicht es Ihnen, alle erworbenen Fähigkeiten in Ihren Kopf zu stecken.
Alles eine angenehme Tageszeit, Chabraviten und diejenigen, die von außen auf diesen Artikel gestoßen sind.