2012-03-25 16 views
27

पर स्थानांतरण मैंने कस्टम स्ट्रक्चर को परिभाषित किया है और MPI_Bsend (या MPI_Send) का उपयोग करके इसे एमपीआई प्रक्रिया में भेजना चाहता हूं।सी में स्ट्रक्चर सीरियलाइजेशन और एमपीआई

यहाँ मेरी struct है:

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

हालांकि, अलग आदिम प्रकार एमपीआई ऊपर struct की तरह जटिल डेटा प्रकार के प्रत्यक्ष "संचरण" का समर्थन नहीं लगती से। मैंने सुना है कि मुझे "क्रमबद्धरण" का उपयोग करना पड़ सकता है। मुझे इसके बारे में कैसे जाना चाहिए और 5 को संसाधित करने के लिए 'myCar' पर भेजना चाहिए?

उत्तर

48

यिर्मयाह सही है - MPI_Type_create_struct यहां जाने का तरीका है।

यह याद रखना महत्वपूर्ण है कि एमपीआई एक पुस्तकालय है, जो भाषा में नहीं बनाया गया है; इसलिए यह "देख" नहीं सकता है कि एक संरचना खुद को क्रमबद्ध करने की तरह दिखती है। तो जटिल डेटा प्रकार भेजने के लिए, आपको स्पष्ट रूप से इसके लेआउट को परिभाषित करना होगा। एक ऐसी भाषा में जिसमें धारावाहिकता के लिए मूल समर्थन है, एमपीआई रैपर का एक सेट निश्चित रूप से इसका उपयोग कर सकता है; उदाहरण के लिए mpi4py जटिल डेटा प्रकारों को पारदर्शी रूप से भेजने के लिए पायथन के pickle का उपयोग करता है; लेकिन सी में, आपको अपनी आस्तीन को रोल करना होगा और इसे स्वयं करना होगा।

अपने संरचना के लिए, यह इस तरह दिखता है:

#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

आपकी बहुत व्यापक और त्वरित प्रतिक्रिया के लिए धन्यवाद। मैं वास्तव में इसकी प्रशंसा करता हूँ। तुमने मुझे पूरी तरह से कवर किया है। (हालांकि मुझे लगता है कि आप शीर्ष कारण पर शामिल करना भूल गए हैं अन्यथा संकलक त्रुटियां देता है ..) – kstratis

+0

आप ऑफसेट() के लिए सही हैं। मैंने कोड को उचित रूप से अपडेट किया है। –

5

अपनी ऑब्जेक्ट के लिए कस्टम एमपीआई डेटाटाइप बनाने के लिए MPI_Type_create_struct पर देखें। इसका उपयोग करने का एक उदाहरण http://beige.ucs.indiana.edu/I590/node100.html पर है।

+0

मैं अभी भी थोड़ा उलझन में हूं .. मान लीजिए कि मैं एमपीआई संरचना को परिभाषित करता हूं और अब इसका उपयोग करना चाहता हूं।आपके द्वारा दिए गए लिंक में कहा गया है: MPI_Type_create_struct (5, array_of_block_lengths, array_of_displacements, array_of_types, और new_type); क्या अब मुझे myCar = & new_type जैसे कुछ करना चाहिए? – kstratis

+0

और बिंदु पर और अधिक ... क्या आप कृपया मुझे विशिष्ट संरचना बनाने और प्रसारित करने का एक सरल लेकिन ठोस उदाहरण दे सकते हैं? – kstratis

+0

समस्या हल हो गई। आपके द्वारा प्रदान किया गया लिंक सभी "सिद्धांत" देता है लेकिन विस्थापन और निम्न स्तर के विवरणों के कारण शौकिया प्रोग्रामर को आसानी से भ्रमित कर सकता है। हालांकि ऐसा लगता है कि नीचे तंत्र का वर्णन किया गया है। – kstratis

6

हालांकि जोनाथन दर्सी के जवाब सही है, यह ज्यादा जटिल है। एमपीआई आपकी समस्या के लिए सरल और कम सामान्य प्रकार के रचनाकारों को अधिक उपयुक्त प्रदान करता है। MPI_Type_create_struct केवल तभी जरूरी है जब आपके पास विभिन्न आधार प्रकार हों (उदा।, एक int और एक फ्लोट)।

अपने उदाहरण के लिए, कई बेहतर समाधान मौजूद हैं:

  • यह मानते हुए कि दो पूर्णांकों (अर्थात पूर्णांकों की एक सरणी की तरह) एक सन्निहित स्मृति क्षेत्र में गठबंधन कर रहे हैं, तो आप एक व्युत्पन्न डेटाप्रकार की जरूरत नहीं है बिलकुल। बस भेजने/बफर प्रकार car के एक चर के पते के साथ प्रकार MPI_INT के दो घटकों को प्राप्त भेजने के रूप में प्रयोग की जाने वाली/प्राप्त करते हैं:

    MPI_Send(&send, 2, MPI_INT, dest, tag, MPI_COMM_WORLD); 
    MPI_Recv(&recv, 2, MPI_INT, src, tag, MPI_COMM_WORLD, &status); 
    
  • आप (जैसे, पठनीयता के लिए या एक व्युत्पन्न डेटाप्रकार उपयोग करना चाहते हैं इसके बारे में मज़ा), तो आपको MPI_Type_contiguous उपयोग कर सकते हैं जो सरणियों से मेल खाती है:

    MPI_Type_contiguous(2, MPI_INT, &mpi_car_type); 
    
  • मामले में दो पूर्णांकों अलग ढंग से सबसे अधिक संभावना मामला नहीं गठबंधन कर रहे हैं (है, लेकिन यह मशीन निर्भर है और एमपीआई कार्यान्वयन एक बहुत के लिए मौजूद हैं विभिन्न प्लेटफार्मों के), आपका उपयोग कर सकते हैं 210: यह विस्थापन की एक सरणी (MPI_Type_create_struct) की तरह लगता है, लेकिन केवल एक ही oldtype तर्क और हर ब्लॉक के ब्लॉक-लंबाई परिभाषा से 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); 
    

जबकि अन्य समाधान शब्दार्थ सही है, तो यह पढ़ने के लिए बहुत कठिन है और एक बड़ा प्रदर्शन जुर्माना लग सकता है।

संबंधित मुद्दे