2012-02-14 12 views
15

Trong MPI, tôi đang thực hiện một hoạt động giảm (tối thiểu) trên một giá trị. Điều này làm việc tốt, nhưng làm thế nào để tôi lấy số lượng bộ xử lý tối thiểu đến và thu hút bộ xử lý đó để biết thêm thông tin (hoặc gửi dữ liệu bổ sung với hoạt động giảm)?MPI Nhận bộ xử lý với giá trị nhỏ nhất

Trả lời

24

Nếu bạn không ngại gọt từng giá trị cục bộ với chỉ số nguyên (được điền trong trường hợp này với giá trị của xếp hạng địa phương), bạn có thể sử dụng hoạt động nội trang MPI_MINLOC or MPI_MAXLOC để giảm; hoặc đó là khá dễ dàng để viết toán tử giảm MPI của riêng bạn để bao gồm những thứ như nhiều chỉ số, etcc

Cập nhật thêm: Với các nhà khai thác MINLOC hoặc MAXLOC BUILTIN, thay vì đi qua trong một giá trị duy nhất để tìm ra tối thiểu , bạn vượt qua trong đó cộng với một chỉ số nguyên. Chỉ mục đó có thể có bất kỳ giá trị nào bạn muốn, nhưng nó "theo sau" giá trị khác cùng. MPI đã xây dựng trong các kiểu dữ liệu "ghép nối" - MPI_DOUBLE_INT cho một double + an int, hoặc MPI_2INT cho hai int, mà bạn có thể sử dụng.

Vì vậy, giả sử bạn muốn tìm tối thiểu một mảng số nguyên và trên đó nhiệm vụ MPI được đặt. Như thường lệ, bạn thấy số tiền tối thiểu địa phương của bạn trên mỗi công việc, và làm giảm; nhưng lần này bạn cũng ghép nối nó với một số nguyên, trong trường hợp này cấp bậc của bạn:

#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; 
} 

Và chạy bạn nhận được:

$ 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 

Nếu giá trị bạn đang giảm không phải là một số nguyên, (giả sử, một đôi), bạn tạo một cấu trúc có chứa giá trị giảm và chỉ số nguyên, và sử dụng kiểu dữ liệu cặp MPI thích hợp. (ví dụ: MPI_DOUBLE_INT).

Cập nhật thêm: Ok, chỉ để cho vui, làm việc đó với hoạt động giảm của chính chúng ta và loại riêng của chúng tôi để thực hiện hai chỉ số:

#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; 
} 

Chạy cho

$ 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

bạn có thể xây dựng hoặc minh họa điều này? –

+0

Cảm ơn, điều đó đã giúp ích rất nhiều! Có thể xác định một cái gì đó như MPI_DOUBLE_2INT vì vậy tôi có thể gửi nhiều hơn một khóa cho mỗi đôi? –

+0

Tôi nghĩ cho bất cứ điều gì khác hơn là các loại nội trang, bạn phải viết hoạt động của riêng bạn, nhưng nó sẽ không được khó khăn. –