2010-02-13 2 views
5

Potrzebuję do MPI_Gatherv() pewnej liczby par int/string. Powiedzmy, że każda para wygląda następująco:Przekazywanie struktur o zmiennej długości między procesami MPI

struct Pair { 
    int x; 
    unsigned s_len; 
    char s[1]; // variable-length string of s_len chars 
}; 

Jak zdefiniować odpowiedni typ danych MPI dla pary?

+0

Użyj 'char s [0];' dla tablicy o zmiennej długości, a nie 'char s [1];'. – kennytm

+0

@KennyTM, s [0] daje "ostrzeżenie C4200: niestandardowe rozszerzenie używane: zero-size array in struct/union". – Constantin

+0

Ah MSVC. C99 jest poprawnie obsługiwane przez gcc, ale nie MSVC. – kennytm

Odpowiedz

4

Krótko mówiąc, teoretycznie niemożliwe jest wysłanie jednej wiadomości o zmiennym rozmiarze i przyjęcie jej do bufora o idealnym rozmiarze. Będziesz musiał wysłać pierwszą wiadomość o rozmiarach każdego ciągu znaków, a następnie drugi komunikat z samymi ciągami lub zakodować te metainfo w polu danych i użyć statycznego bufora odbiorczego.

Jeśli musisz wysłać tylko jedną wiadomość, to zrezygnuję z określenia typu dla pary: zamiast tego utworzę typ danych dla całego ładunku i zrzucę wszystkie dane do jednego, ciągłego, nienumerowanego pakietu. Następnie na końcu odbierającym można go przetworzyć, przydzielając dokładną ilość miejsca potrzebnego na każdy ciąg i wypełniając go. Pozwól mi pobudzić diagram ASCII do zilustrowania. To byłby twój ładunek:

| ..x1 .. | ..s_len1 .. | .... string1 .... | ..x2 .. | ..s_len2 .. | .string2. |. .x3 .. | .s_len3 .. | ....... string3 ....... | ...

Wysyłasz całość jako jedną jednostkę (np. tablicę MPI_BYTE), wówczas odbiornik będzie rozpakować coś takiego:

while (buffer is not empty) 
{ 
    read x; 
    read s_len; 
    allocate s_len characters; 
    move s_len characters from buffer to allocated space; 
} 

Należy jednak pamiętać, że to rozwiązanie działa tylko wtedy, gdy reprezentacja danych liczb i znaków jest taka sama na wysyłających i przyjmujących systemów.

+0

Pakowanie wszystkiego w sąsiadującym buforze jest tym, na czym ostatecznie się zdecydowałem. Jedna rzecz, którą należy zauważyć, to że musiałem użyć dodatkowego MPI_Gather(), aby zebrać rozmiary danych z każdego procesu. Te wielkości ładunku użyto do obliczenia wielkości bufora recv i wektora przemieszczenia (http://www.mpi-forum.org/docs/mpi-11-html/node70.html). – Constantin

2

Nie sądzę, że możesz zrobić całkiem, co chcesz z MPI. Jestem programistą z Fortranu, więc nie przejmujcie się, jeśli moje rozumienie C jest trochę niepewne. Chcesz, zdaje się, przekazać strukturę danych składającą się z 1 int i 1 napisu (który przekazujesz, przekazując lokalizację pierwszego znaku w ciągu) z jednego procesu do drugiego? Myślę, że to, co musisz zrobić, to przekazać ciąg o stałej długości, który miałby być tak długi, jak każdy z ciągów, które naprawdę chcesz przekazać. Strefa przyjęć do zbierania tych strun będzie musiała być wystarczająco duża, aby pomieścić wszystkie struny wraz z ich długościami.

Prawdopodobnie będziesz chciał zadeklarować nowy typ danych MPI dla twoich struktur; możesz je następnie zebrać, a ponieważ zebrane dane zawierają długość ciągu, odzyskaj użyteczne części ciągu w odbiorniku.

Nie jestem tego pewien, ale nigdy nie natknąłem się na naprawdę zmienne długości wiadomości, ponieważ wydaje się, że chcesz ich używać, a ich sortowanie jest podobne do MPI. Ale może to być coś, co zostało zaimplementowane w najnowszej wersji MPI, na którą nigdy się nie natknąłem, chociaż patrząc na dokumentację on-line nie wydaje się tak.

+0

Miałem nadzieję uniknąć marnowania miejsca przy użyciu buforów o stałej długości. Inną możliwą opcją, której należy unikać, jest reprezentowanie układu par len/znaków z 2 oddzielnymi tablicami: jeden z soczewki i jeden z znaków. Dzięki i tak. – Constantin

+0

Mark, minęło trochę czasu, odkąd bawiłem się z MPI, ale jestem prawie pewien, że jesteś dokładny tutaj. Przynajmniej na okres około 2005 MPI. –

1

Implementacje MPI nie sprawdzają ani nie interpretują rzeczywistej zawartości wiadomości. Pod warunkiem, że znasz rozmiar struktury danych, możesz reprezentować ten rozmiar w pewnej liczbie znaków char lub int. Implementacja MPI nie będzie wiedziała ani dba o rzeczywiste wewnętrzne szczegóły danych.

Jest kilka zastrzeżeń ... zarówno nadawca, jak i odbiorca muszą uzgodnić interpretację treści wiadomości, a bufor, który podajesz po stronie nadawczej i odbiorczej, musi pasować do określonej liczby znaków int.