2012-03-25 34 views
27

Özel bir yapı tanımladım ve MPI_Bsend (veya MPI_Send) kullanarak başka bir MPI işlemine göndermek istiyorum.C yapı serileştirmesi ve MPI üzerinden aktarım

İşte benim yapıdır:

struct car{ 
    int shifts; 
    int topSpeed; 
}myCar; 

Ancak, ayrı MPİ yukarıdaki yapı gibi karmaşık veri tiplerinin doğrudan "iletim" desteklemek için görünmüyor ilkel türlerinden. "Serileştirme" kullanmam gerektiğini duydum. Bunun için nasıl gidip, 5 sürecine 'myCar'ı göndermeliyim?

cevap

48

Yeremya doğru - MPI_Type_create_struct buraya gitmenin yoludur.

MPI'nin bir dil kütüphanesi değil, dilin içine yerleştirildiğini hatırlamak önemlidir; Dolayısıyla, bir yapının kendi kendini serileştirmek için neye benzediğini "göremez". Bu yüzden karmaşık veri türleri göndermek için, düzenini açıkça tanımlamanız gerekir. Serileştirme için yerel desteğe sahip bir dilde, bir dizi MPI sarıcısı, bundan faydalanarak faydalanabilir; Örneğin, mpi4py, karmaşık veri türlerini şeffaf bir şekilde göndermek için python'un pickle kullanımını kullanır; ama C’de kollarınızı yukarı kaldırmanız ve kendiniz yapmalısınız. senin yapısı için

, bu şuna benzer: Jonathan Dursi cevabı doğru olmasına rağmen

#include <stdio.h> 
#include <stdlib.h> 
#include <mpi.h> 
#include <stddef.h> 

typedef struct car_s { 
     int shifts; 
     int topSpeed; 
} car; 

int main(int argc, char **argv) { 

    const int tag = 13; 
    int size, rank; 

    MPI_Init(&argc, &argv); 
    MPI_Comm_size(MPI_COMM_WORLD, &size); 

    if (size < 2) { 
     fprintf(stderr,"Requires at least two processes.\n"); 
     exit(-1); 
    } 

    /* create a type for struct car */ 
    const int nitems=2; 
    int   blocklengths[2] = {1,1}; 
    MPI_Datatype types[2] = {MPI_INT, MPI_INT}; 
    MPI_Datatype mpi_car_type; 
    MPI_Aint  offsets[2]; 

    offsets[0] = offsetof(car, shifts); 
    offsets[1] = offsetof(car, topSpeed); 

    MPI_Type_create_struct(nitems, blocklengths, offsets, types, &mpi_car_type); 
    MPI_Type_commit(&mpi_car_type); 

    MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
    if (rank == 0) { 
     car send; 
     send.shifts = 4; 
     send.topSpeed = 100; 

     const int dest = 1; 
     MPI_Send(&send, 1, mpi_car_type, dest, tag, MPI_COMM_WORLD); 

     printf("Rank %d: sent structure car\n", rank); 
    } 
    if (rank == 1) { 
     MPI_Status status; 
     const int src=0; 

     car recv; 

     MPI_Recv(&recv, 1, mpi_car_type, src, tag, MPI_COMM_WORLD, &status); 
     printf("Rank %d: Received: shifts = %d topSpeed = %d\n", rank, 
       recv.shifts, recv.topSpeed); 
    } 

    MPI_Type_free(&mpi_car_type); 
    MPI_Finalize(); 

    return 0; 
} 
+0

Çok kapsamlı ve hızlı yanıtınız için teşekkür ederiz. Gerçekten onu takdir ederim. Beni tamamen örttün. (Ancak derhal 'u en iyi nedene dahil etmeyi unuttuğunuzu düşünüyorum, aksi takdirde derleyici hata verir ..) – kstratis

+0

Haklısınız - offsetof() için gereklidir. Kodu uygun şekilde güncelledim. –

5

Nesneniz için özel bir MPI veri türü oluşturmak için MPI_Type_create_struct'a bakın. Kullanmanın bir örneği http://beige.ucs.indiana.edu/I590/node100.html'dur.

+0

Hala biraz kafam karıştı .. MPI yapısını tanımladığımı ve şimdi kullanmak istediğimi varsayalım.Verdiğiniz bağlantı: MPI_Type_create_struct (5, array_of_block_lengths, array_of_displacements, array_of_types ve new_type); Şimdi myCar = & new_type gibi bir şey yapmalı mıyım? – kstratis

+0

Ve daha fazlası için ... Bana belirli bir yapıyı oluşturma ve iletme basit ama somut bir örnek verebilir misiniz? – kstratis

+0

Sorun çözüldü. Sağladığınız link, tüm "teori" ni verir, ancak deplasmanlar ve düşük seviye detayları nedeniyle amatör programcıları kolayca karıştırır. Ancak, altındaki mekanizmayı tam olarak açıklıyor gibi görünüyor. – kstratis

6

, bu aşırı karmaşık olduğunu. MPI, probleminiz için daha basit ve daha az genel tip kurucular sağlar. MPI_Type_create_struct SADECE farklı taban türlerine (ör. Int ve float) sahip olduğunuzda gereklidir.

senin Örneğin

, birkaç iyi çözümler vardır:

  • iki tamsayı (tam sayılar dizisi gibi, yani) bitişik bir bellek alanında hizalanmış varsayarsak, türetilmiş bir veri türü gerekmez hiç Sadece/alma tampon tipi car bir değişkenin adresi ile tip MPI_INT iki elemanlarını almak gönderme olarak kullanılmak üzere göndermek /:

    MPI_Send(&send, 2, MPI_INT, dest, tag, MPI_COMM_WORLD); 
    MPI_Recv(&recv, 2, MPI_INT, src, tag, MPI_COMM_WORLD, &status); 
    
  • Eğer örneğin okunabilmesi için ya da (türetilmiş bir veri türü kullanmak isterseniz dizilerin tekabül bunun eğlenceli), sen MPI_Type_contiguous kullanabilirsiniz:

    MPI_Type_contiguous(2, MPI_INT, &mpi_car_type); 
    
  • durumda iki tamsayı (farklı durum büyük olasılıkla değil hizalanmış ama makineden bağımsız ve MPI uygulaması bir çok ana kadar farklı platformlar),kullanabilirsiniz 210: Bu, yer değiştirme bir dizi (MPI_Type_create_struct gibi) alır, ancak sadece tek bir eskitür bağımsız değişken ve her bloğun blok uzunluğu tanım olarak, 1:

    MPI_Aint offsets[2]; 
    offsets[0] = offsetof(car, shifts) ; //most likely going to be 0 
    offsets[1] = offsetof(car, topSpeed); 
    MPI_Type_indexed_block(2, offsets, MPI_INT); 
    

Diğer çözüm semantik doğru olsa da, bu okumak için çok daha zor ve büyük bir performans cezasına çarptırılabilir.