2012-02-14 15 views
15

एमपीआई में, मैं मूल्य पर एक कम ऑपरेशन (न्यूनतम) कर रहा हूं। यह ठीक काम करता है, लेकिन मैं प्रोसेसर संख्या को कैसे पकड़ूं जो कम से कम आया था और अधिक जानकारी के लिए प्रोसेसर को मांगता है (या कम ऑपरेशन के साथ अतिरिक्त डेटा भेजता है)?एमपीआई न्यूनतम मूल्य के साथ प्रोसेसर प्राप्त करें

उत्तर

24

यदि आप एक पूर्णांक सूचकांक (स्थानीय रैंक के मूल्य के साथ इस मामले में भरे हुए) के साथ स्थानीय रूप से प्रत्येक मान को समानता से ध्यान नहीं देते हैं, तो आप MPI_MINLOC or MPI_MAXLOC बिल्टिन ऑपरेशंस को कम करने के लिए उपयोग कर सकते हैं; या यह अपने स्वयं के एमपीआई कमी ऑपरेटर कई सूचकांकों तरह बातें शामिल करने के लिए लिखने के लिए काफी आसान है etcc

जोड़ने के लिए अपडेट किया गया: builtin ऑपरेटरों MINLOC या MAXLOC साथ , बजाय एक ही मूल्य में पास करने का कम से कम लगता है की , आप उस प्लस को एक पूर्णांक अनुक्रमणिका में पास करते हैं। उस इंडेक्स में कोई वैल्यू हो सकता है जिसे आप चाहते हैं, लेकिन यह अन्य मूल्य के साथ "निम्न" है। एमपीआई ने "जोड़ी" डेटा प्रकारों में बनाया है - MPI_DOUBLE_INT दो इंच के लिए एक डबल + एक int, या MPI_2INT के लिए, जिसका उपयोग आप कर सकते हैं।

तो कहें कि आप न्यूनतम पूर्णांक सरणी ढूंढना चाहते हैं, और जिस पर एमपीआई कार्य यह स्थित था। सामान्य रूप से, आप प्रत्येक कार्य पर अपना स्थानीय न्यूनतम पाते हैं, और कम करते हैं; लेकिन इस बार आप भी यह एक पूर्णांक के साथ अपने पद जोड़ी, इस मामले में:

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

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

    int rank, size; 
    const int locn=5; 
    int localarr[locn]; 

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

    srand(rank); 
    for (int i=0; i<locn; i++) 
     localarr[i] = rand() % 100; 

    for (int proc=0; proc<size; proc++) { 
     if (rank == proc) { 
      printf("Rank %2d has values: ",rank); 
      for (int i=0; i<locn; i++) 
       printf(" %d ", localarr[i]); 
      printf("\n"); 
     } 
     MPI_Barrier(MPI_COMM_WORLD); 
    } 

    int localres[2]; 
    int globalres[2]; 
    localres[0] = localarr[0]; 
    for (int i=1; i<locn; i++) 
     if (localarr[i] < localres[0]) localres[0] = localarr[i]; 

    localres[1] = rank; 

    MPI_Allreduce(localres, globalres, 1, MPI_2INT, MPI_MINLOC, MPI_COMM_WORLD); 

    if (rank == 0) { 
     printf("Rank %d has lowest value of %d\n", globalres[1], globalres[0]); 
    } 

    MPI_Finalize(); 

    return 0; 
} 

और तुम मिल चल:

$ mpirun -np 5 ./minloc 
Rank 0 has values: 83 86 77 15 93 
Rank 1 has values: 83 86 77 15 93 
Rank 2 has values: 90 19 88 75 61 
Rank 3 has values: 46 85 68 40 25 
Rank 4 has values: 1 83 74 26 63 
Rank 4 has lowest value of 1 

यदि आप जो मान को कम करने कर रहे हैं एक पूर्णांक नहीं है, (कहें, एक डबल), आप एक संरचना बनाते हैं जिसमें कमी मूल्य और पूर्णांक अनुक्रमणिका होती है, और उपयुक्त एमपीआई जोड़ी डेटा प्रकार का उपयोग करें। (उदाहरण के लिए, MPI_DOUBLE_INT)।

Updated आगे: ठीक है, सिर्फ मनोरंजन, हमारे अपने कमी आपरेशन और हमारे अपने प्रकार के साथ यह करने के लिए लागू करने के लिए दो सूचकांक:

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

typedef struct dbl_twoindex_struct { 
    double val; 
    int rank; 
    int posn; 
} dbl_twoindex; 


void minloc_dbl_twoindex(void *in, void *inout, int *len, MPI_Datatype *type){ 
    /* ignore type, just trust that it's our dbl_twoindex type */ 
    dbl_twoindex *invals = in; 
    dbl_twoindex *inoutvals = inout; 

    for (int i=0; i<*len; i++) { 
     if (invals[i].val < inoutvals[i].val) { 
      inoutvals[i].val = invals[i].val; 
      inoutvals[i].rank = invals[i].rank; 
      inoutvals[i].posn = invals[i].posn; 
     } 
    } 

    return; 
} 


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

    int rank, size; 
    const int locn=5; 
    double localarr[locn]; 

    dbl_twoindex local, global; 

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

    /* create our new data type */ 
    MPI_Datatype mpi_dbl_twoindex; 
    MPI_Datatype types[3] = { MPI_DOUBLE, MPI_INT, MPI_INT }; 
    MPI_Aint disps[3] = { offsetof(dbl_twoindex, val), 
        offsetof(dbl_twoindex, rank), 
        offsetof(dbl_twoindex, posn), }; 
    int lens[3] = {1,1,1}; 
    MPI_Type_create_struct(3, lens, disps, types, &mpi_dbl_twoindex); 
    MPI_Type_commit(&mpi_dbl_twoindex); 

    /* create our operator */ 
    MPI_Op mpi_minloc_dbl_twoindex; 
    MPI_Op_create(minloc_dbl_twoindex, 1, &mpi_minloc_dbl_twoindex); 

    srand(rank); 
    for (int i=0; i<locn; i++) 
     localarr[i] = 1.*rand()/RAND_MAX; 

    for (int proc=0; proc<size; proc++) { 
     if (rank == proc) { 
      printf("Rank %2d has values: ",rank); 
      for (int i=0; i<locn; i++) 
       printf(" %8.4lf ", localarr[i]); 
      printf("\n"); 
     } 
     MPI_Barrier(MPI_COMM_WORLD); 
    } 

    local.val = localarr[0]; 
    local.posn = 0; 
    for (int i=1; i<locn; i++) 
     if (localarr[i] < local.val) { 
       local.val = localarr[i]; 
       local.posn = i; 
     } 
    local.rank = rank; 

    MPI_Allreduce(&local, &global, 1, mpi_dbl_twoindex, mpi_minloc_dbl_twoindex, MPI_COMM_WORLD); 

    if (rank == 0) { 
     printf("Rank %d has lowest value of %8.4lf in position %d.\n", global.rank, global.val, global.posn); 
    } 

    MPI_Op_free(&mpi_minloc_dbl_twoindex); 
    MPI_Type_free(&mpi_dbl_twoindex); 
    MPI_Finalize(); 

    return 0; 
} 

रनिंग देता

$ mpirun -np 5 ./minloc2 
Rank 0 has values: 0.8402 0.3944 0.7831 0.7984 0.9116 
Rank 1 has values: 0.8402 0.3944 0.7831 0.7984 0.9116 
Rank 2 has values: 0.7010 0.8097 0.0888 0.1215 0.3483 
Rank 3 has values: 0.5614 0.2250 0.3931 0.4439 0.2850 
Rank 4 has values: 0.9165 0.1340 0.1912 0.2601 0.2143 
Rank 2 has lowest value of 0.0888 in position 2. 
+0

आप विस्तार से बता सकते हैं या इसका उदाहरण है? –

+0

धन्यवाद, इससे बहुत मदद मिली! क्या कोई MPI_DOUBLE_2INT जैसे कुछ परिभाषित कर सकता है ताकि मैं प्रति डबल एक से अधिक कुंजी भेज सकूं? –

+0

मैं बिल्टिन प्रकारों के अलावा किसी भी चीज़ के लिए सोचता हूं, आपको अपना खुद का ऑपरेशन लिखना होगा, लेकिन यह मुश्किल नहीं होगा। –

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