*
Hi
Ich habe ein einfaches Programm geschrieben, welches das Message Passing Interface benutzt. Leider erhalte ich immer irgendwelche Debug Assertion.
#include "mpi.h"
#include "windows.h"
#include "assert.h"
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
typedef unsigned long long ullong;
// Zahl welche es zu faktorisieren gilt
ullong factnum = 12222222222222;
// MPI Tags, Faktor gefunden
const int tagfactfound = 1;
// Auftragverteilung
const int tagbeginjob = 2;
// Auftrag beendet
const int tagendjob = 3;
int myid;
// Berechnet die Quadratwurzel eine Variable des Typs unsigned long long
ullong ulsqrt(ullong num){
/*__asm {
// Double word move (64bit)
movq mm1,num
// Konvertiere two double int (64bit) to double pr. float (128bit)
cvtpi2pd xmm0,mm1
// Quadratwurzel ziehen
sqrtsd xmm0,xmm0
// Konvertiere double pr. float (128bit) to two double int (64bit)
cvtpd2pi eax,xmm0
}*/
return sqrt((long double)num);
}
// Funktion welche anhand des Sieb des Eratosthenes überprüft ob eine Zahl
// Primfaktoren besitzt
bool isprime(ullong num){
assert (num % 2 == 1);
// Grösster Teiler
ullong max = ulsqrt(num);
// Boolsches Array auf dem Heap allozieren
bool * eratos = new bool[max];
// Primzahlenspeicher
ullong * prim = new ullong[max/2];
ullong count = 0;
// Primzahlen besimmten
for (ullong i=2; i <= max; ++i){
// Zahl ist prim
if (eratos[i]){
prim[i] = i;
count++;
}
// Alle Vielfachen als nicht prim markieren
ullong j = i*i;
while (j <= max){
eratos[j] = false;
j += j;
}
}
// Zahl anhand der vorher berechneten Primzahlen überprüfen
for (ullong i=0; i < count; ++i){
if(num % prim[i] == 0)return false;
}
return true;
}
// Diese Funktion überprüft ob die Zahl num eine Primzahl ist, falls nicht
// liefert sie die nächstmögliche Primzahl
ullong getnextprime(ullong num){
if (num == 0 || num == 1) return 2;
// Nächste Primzahl berechnen wenn num nicht prim ist
while(!isprime(num)){
num += 2;
}
return num;
}
int main(int argc, char* argv[]) {
// Message Passing Interface initalisieren
MPI::Init(argc, argv);
// Anzahl der Nodes ermitteln
int numprocs = MPI::COMM_WORLD.Get_size();
if (numprocs < 2){
printf("Need than one process for calculation\n");
return 0;
}
// Welcher Node bin ich?
myid = MPI::COMM_WORLD.Get_rank();
MPI::Status stat;
ullong jobmax = ulsqrt(factnum);
ullong jobsize = ceil((long double)(jobmax)/(long double)(numprocs-1));
ullong jobcounter = 0;
std::vector<ullong> fact;
// Managernode
if (myid == 0) {
printf("Beginning of job distribution for %d workers with candidate %lld\n",numprocs,factnum);
// Ausgabe sofort an die Pipe senden
fflush(stdout);
// Jedem Workernode einen Auftrag übergeben
for (int i = 1; i < numprocs; ++i){
printf("Distribut job (%lld ",jobcounter);
jobcounter += jobsize;
printf("to %lld) to %d\n",jobcounter,i);
fflush(stdout);
// Jeweiligen Auftrag an den jeweiligen Arbeit schicken
MPI::COMM_WORLD.Send(&jobcounter, sizeof(ullong), MPI::UNSIGNED_LONG_LONG,i,tagbeginjob);
}
do {
while (MPI::COMM_WORLD.Iprobe(MPI::ANY_SOURCE,tagendjob,stat))
{
int b;
// Leer Benachrichtung aus dem Speicher entferne
MPI::COMM_WORLD.Recv(&b,sizeof(b),MPI::INT,MPI::ANY_SOURCE,tagendjob,stat);
// Ein Arbeiter wurde fertig
--numprocs;
}
while (MPI::COMM_WORLD.Iprobe(MPI::ANY_SOURCE,tagfactfound,stat))
{
// Ein Arbeiter hat einen Faktor gefunden
ullong lbuf;
// Faktor aus Nachrichtenspeicher holen
MPI::COMM_WORLD.Recv(&lbuf,sizeof(lbuf),MPI::UNSIGNED_LONG_LONG,MPI::ANY_SOURCE,tagfactfound,stat);
// Zahl minimieren
factnum /= lbuf;
// Dem Faktorenvektor hinzufügen
fact.push_back(lbuf);
}
} while (numprocs != 1);
if (factnum != 1) fact.push_back(factnum);
// Alle Arbeiter haben ihren Auftrag erledigt
printf("Factors: ");
std::copy(fact.begin(),fact.end(),std::ostream_iterator<ullong>(std::cout," "));
printf("\n");
// Workernodes
} else {
ullong fbuf;
// Auftrag empfangen
MPI::COMM_WORLD.Recv(&fbuf,sizeof(fbuf),MPI::UNSIGNED_LONG_LONG,MPI::ANY_SOURCE,tagbeginjob);
// Untere Grenze bestimmen;
ullong minsize = fbuf-jobsize;
// Alle ungeraden Zahlen werden überprüft
if (minsize % 2 == 0) ++minsize;
ullong maxsize = fbuf;
printf("Worker %d got Job %lld to %lld\n",myid,minsize,fbuf);
fflush(stdout);
ullong i = getnextprime(minsize);
ullong g;
// Auftrag bearbeiten
while(i < maxsize){
// Hat ein andere Arbeiter einen Faktor gefunden?
if (MPI::COMM_WORLD.Iprobe(MPI::ANY_SOURCE,tagfactfound,stat)){
ullong lbuf;
// Faktor auslesen
MPI::COMM_WORLD.Recv(&lbuf,sizeof(lbuf),MPI::UNSIGNED_LONG_LONG,MPI::ANY_SOURCE,tagfactfound);
// Zahl minimieren
factnum /= lbuf;
}
g = 1;
// Wir haben einen Faktor gefunden
if (factnum % i == 0){
ullong lbuf = i;
// Zahl minimieren
factnum = factnum / lbuf;
for (int l = 0; l < MPI::COMM_WORLD.Get_size(); ++l)
{
if (l != myid){
// Den anderen Arbeitern und dem Manager mitteilen
MPI::COMM_WORLD.Send(&lbuf, sizeof(lbuf),MPI::UNSIGNED_LONG_LONG,l,tagfactfound);
}
}
} else {
// Nächste Primzahl generieren
if (i == 2) i = 3;
else i = getnextprime(i+2);
fflush(stdout);
}
}
// Auftrag wurde erledigt
int b = 1;
MPI::COMM_WORLD.Send(&b,sizeof(b),MPI::INT,0,tagendjob);
}
// Message Passing Interface Umgebung beenden
MPI::Finalize();
return 0;
}
Die Fehler passieren immer bei einem Aufruf von Recv. Ich habe schon diverse MPI Dokumente studiert, jedoch nichts gefunden was ich falsch gemacht habe. Das Programm funktionierte mit unsigned long.
MfG Joe