Das array
sollte 100 statt 10 sein, da Sie 10 Floats pro Zeile zuweisen. JackNs Antwort hat den Code dafür.
Bei jedem anderen Prozess als Rang 0 ist der Zeiger auf das Array jedoch null
.
Sie müssen das Array für alle Prozesse initialisieren und anschließend das Array im Root-Verzeichnis füllen.
Sie können den Malloc-Code einfach aus dem if (rank ==0)
-Block entfernen und er sollte wie erwartet funktionieren.
Hier gibt es drei Punkte - einer mit Zuweisungen, einer mit Zuordnung und einer mit der Funktionsweise von MPI, und keine der anderen Antworten berührt sie alle.
Das erste und wichtigste Problem ist, wo Dinge zugeteilt werden. Wie von @davidb richtig ausgeführt, reserviert man Speicher nur für Task Null, so dass die anderen Tasks keinen Speicher haben, in dem die Übertragung empfangen werden kann.
Wie für 2d Allokationen in C im Allgemeinen ist Ihr Code fast genau richtig. In diesem Codeblock:
%Vor%Das einzige wirkliche Problem ist, dass das erste malloc aus 10 float Zeigern bestehen sollte, nicht aus Floaten:
%Vor%Darauf hat @eznme hingewiesen. Der erste Weg funktioniert möglicherweise abhängig von dem Speichermodell, mit dem Sie kompilieren / verlinken usw. und wird mit hoher Wahrscheinlichkeit auf 32-Bit-Betriebssystemen / -Maschinen funktionieren - aber nur weil es funktioniert, bedeutet es nicht immer, dass es richtig ist:)
Nun, das letzte Problem ist, dass Sie ein perfektes 2d-Array in C deklariert haben, aber das ist nicht das, was MPI erwartet. Wenn Sie diesen Anruf tätigen,
%Vor% Sie sagen MPI, dass sie 100 zusammenhängende Floats senden soll, auf die von array
gezeigt wird. Sie bemerken, dass die Bibliotheksroutine nicht wissen kann, ob Array der Zeiger auf den Anfang eines 2D- oder 3D- oder 12D-Arrays ist oder wie die einzelnen Dimensionen sind; es weiß nicht, ob es den Zeigern folgen muss, und wenn es so wäre, wüsste es nicht, wie viele es folgen sollen.
Sie möchten also einen Float-Zeiger an 100 zusammenhängende Floats senden - und in der normalen C-Weise zum Zuweisen von pseudo-multidimensionalen Arrays (*) müssen Sie das nicht unbedingt haben. Sie wissen nicht unbedingt, wie weit die 2. Reihe von der 1. Reihe in diesem Layout entfernt ist - oder auch in welche Richtung. Was Sie also wirklich tun möchten, ist etwa so:
%Vor%Auf diese Weise und nur auf diese Weise ist garantiert, dass der Speicher zusammenhängend ist. Dann können Sie
tun %Vor% Beachten Sie, dass Sie für eine beliebige Anordnung von Daten immer noch Bcast
verwenden könnten, indem Sie einen MPI-Datentyp definieren, der beschreibt, wie das 2d-Array tatsächlich im Speicher angeordnet ist; aber das ist einfacher und näher an dem, was Sie wahrscheinlich wirklich wollen.
(*) Das wirkliche Problem hier ist, dass C- und C-abgeleitete Sprachen keine echten Multi-D-Arrays als erstklassige Objekte haben - was für eine Systemprogrammiersprache gut ist, aber bei der wissenschaftlichen Programmierung irritierend ist.
Ich versuche ein dynamisches 2d-Array mit bcast an alle Ränge zu übergeben. Ich habe den folgenden Code.
%Vor%Aus irgendeinem Grund kann ich nicht verstehen, dass ich einen Segmentierungsfehler bekomme. Wer weiß, wo das Problem ist?
Wahrscheinlich möchten Sie das erste malloc in
ändern %Vor%, weil das Array Zeiger speichert und Gleitkommazahlen anstelle von Eingängen speichert:
%Vor%Wenn Sie ein Array mit 10 * 10 belegen möchten, geben Sie Ihren Code ein:
%Vor%sollte
sein %Vor%Hier gibt es drei Punkte - einer mit Zuweisungen, einer mit Zuordnung und einer mit der Funktionsweise von MPI, und keine der anderen Antworten berührt sie alle.
Das erste und wichtigste Problem ist, wo Dinge zugeteilt werden. Wie von @davidb richtig ausgeführt, reserviert man Speicher nur für Task Null, so dass die anderen Tasks keinen Speicher haben, in dem die Übertragung empfangen werden kann.
Wie für 2d Allokationen in C im Allgemeinen ist Ihr Code fast genau richtig. In diesem Codeblock:
%Vor%Das einzige wirkliche Problem ist, dass das erste malloc aus 10 float Zeigern bestehen sollte, nicht aus Floaten:
%Vor%Darauf hat @eznme hingewiesen. Der erste Weg funktioniert möglicherweise abhängig von dem Speichermodell, mit dem Sie kompilieren / verlinken usw. und wird mit hoher Wahrscheinlichkeit auf 32-Bit-Betriebssystemen / -Maschinen funktionieren - aber nur weil es funktioniert, bedeutet es nicht immer, dass es richtig ist:)
Nun, das letzte Problem ist, dass Sie ein perfektes 2d-Array in C deklariert haben, aber das ist nicht das, was MPI erwartet. Wenn Sie diesen Anruf tätigen,
%Vor%Sie sagen MPI, dass sie 100 zusammenhängende Floats senden soll, auf die von %code% gezeigt wird. Sie bemerken, dass die Bibliotheksroutine nicht wissen kann, ob Array der Zeiger auf den Anfang eines 2D- oder 3D- oder 12D-Arrays ist oder wie die einzelnen Dimensionen sind; es weiß nicht, ob es den Zeigern folgen muss, und wenn es so wäre, wüsste es nicht, wie viele es folgen sollen.
Sie möchten also einen Float-Zeiger an 100 zusammenhängende Floats senden - und in der normalen C-Weise zum Zuweisen von pseudo-multidimensionalen Arrays (*) müssen Sie das nicht unbedingt haben. Sie wissen nicht unbedingt, wie weit die 2. Reihe von der 1. Reihe in diesem Layout entfernt ist - oder auch in welche Richtung. Was Sie also wirklich tun möchten, ist etwa so:
%Vor%Auf diese Weise und nur auf diese Weise ist garantiert, dass der Speicher zusammenhängend ist. Dann können Sie
tun %Vor%Beachten Sie, dass Sie für eine beliebige Anordnung von Daten immer noch %code% verwenden könnten, indem Sie einen MPI-Datentyp definieren, der beschreibt, wie das 2d-Array tatsächlich im Speicher angeordnet ist; aber das ist einfacher und näher an dem, was Sie wahrscheinlich wirklich wollen.
(*) Das wirkliche Problem hier ist, dass C- und C-abgeleitete Sprachen keine echten Multi-D-Arrays als erstklassige Objekte haben - was für eine Systemprogrammiersprache gut ist, aber bei der wissenschaftlichen Programmierung irritierend ist.
Das %code% sollte 100 statt 10 sein, da Sie 10 Floats pro Zeile zuweisen. JackNs Antwort hat den Code dafür.
Bei jedem anderen Prozess als Rang 0 ist der Zeiger auf das Array jedoch %code% . Sie müssen das Array für alle Prozesse initialisieren und anschließend das Array im Root-Verzeichnis füllen.
Sie können den Malloc-Code einfach aus dem %code% -Block entfernen und er sollte wie erwartet funktionieren.
Wahrscheinlich möchten Sie das erste malloc in
ändern %Vor%, weil das Array Zeiger speichert und Gleitkommazahlen anstelle von Eingängen speichert:
%Vor%