2016-10-10 21 views
9

Chương trình này được viết bằng C Lagrange và MPI. Tôi mới sử dụng MPI và muốn sử dụng tất cả các bộ vi xử lý để thực hiện một số tính toán, bao gồm quy trình 0. Để tìm hiểu khái niệm này, tôi đã viết chương trình đơn giản sau đây. Nhưng chương trình này được treo ở phía dưới sau khi nhận được thông tin từ quá trình 0 và sẽ không gửi kết quả lại cho quá trình 0.Cách Gửi/Nhận trong Bộ KH & ĐT bằng cách sử dụng tất cả bộ xử lý

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

int main(int argc, char** argv) {  
    MPI_Init(&argc, &argv); 
    int world_rank; 
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); 
    int world_size; 
    MPI_Comm_size(MPI_COMM_WORLD, &world_size); 

    int number; 
    int result; 
    if (world_rank == 0) 
    { 
     number = -2; 
     int i; 
     for(i = 0; i < 4; i++) 
     { 
      MPI_Send(&number, 1, MPI_INT, i, 0, MPI_COMM_WORLD); 
     } 
     for(i = 0; i < 4; i++) 
     {   /*Error: can't get result send by other processos bellow*/ 
      MPI_Recv(&number, 1, MPI_INT, i, 99, MPI_COMM_WORLD, MPI_STATUS_IGNORE); 
      printf("Process 0 received number %d from i:%d\n", number, i); 
     } 
    } 
    /*I want to do this without using an else statement here, so that I can use process 0 to do some calculations as well*/ 

    MPI_Recv(&number, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); 
    printf("*Process %d received number %d from process 0\n",world_rank, number); 
    result = world_rank + 1; 
    MPI_Send(&result, 1, MPI_INT, 0, 99, MPI_COMM_WORLD); /* problem happens here when trying to send result back to process 0*/ 

    MPI_Finalize(); 
} 

runing và nhận được kết quả:

:$ mpicc test.c -o test 
:$ mpirun -np 4 test 

*Process 1 received number -2 from process 0 
*Process 2 received number -2 from process 0 
*Process 3 received number -2 from process 0 
/* hangs here and will not continue */ 

Nếu bạn có thể , vui lòng chỉ cho tôi một ví dụ hoặc chỉnh sửa mã ở trên nếu có thể.

Trả lời

1

Tôi thực sự không hiểu điều gì sẽ sai khi sử dụng các câu lệnh 2 if, xung quanh miền hoạt động. Nhưng dù sao, đây là một ví dụ về những gì có thể được thực hiện.

Tôi đã sửa đổi mã của bạn để sử dụng thông tin liên lạc tập thể vì chúng có ý nghĩa hơn nhiều so với chuỗi gửi/nhận bạn đã sử dụng. Vì các liên lạc ban đầu có giá trị thống nhất, tôi sử dụng một số MPI_Bcast() thực hiện tương tự trong một cuộc gọi duy nhất.
Ngược lại, vì giá trị kết quả khác nhau, nên gọi tới số MPI_Gather() là hoàn toàn phù hợp.
Tôi cũng giới thiệu một cuộc gọi đến sleep() chỉ để mô phỏng rằng các quy trình đang hoạt động trong một thời gian, trước khi gửi lại kết quả của chúng.

Mã bây giờ trông như thế này:

#include <mpi.h> 
#include <stdlib.h> // for malloc and free 
#include <stdio.h> // for printf 
#include <unistd.h> // for sleep 

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

    MPI_Init(&argc, &argv); 
    int world_rank; 
    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); 
    int world_size; 
    MPI_Comm_size(MPI_COMM_WORLD, &world_size); 

    // sending the same number to all processes via broadcast from process 0 
    int number = world_rank == 0 ? -2 : 0; 
    MPI_Bcast(&number, 1, MPI_INT, 0, MPI_COMM_WORLD); 
    printf("Process %d received %d from process 0\n", world_rank, number); 

    // Do something usefull here 
    sleep(1); 
    int my_result = world_rank + 1; 

    // Now collecting individual results on process 0 
    int *results = world_rank == 0 ? malloc(world_size * sizeof(int)) : NULL; 
    MPI_Gather(&my_result, 1, MPI_INT, results, 1, MPI_INT, 0, MPI_COMM_WORLD); 

    // Process 0 prints what it collected 
    if (world_rank == 0) { 
     for (int i = 0; i < world_size; i++) { 
      printf("Process 0 received result %d from process %d\n", results[i], i); 
     } 
     free(results); 
    } 

    MPI_Finalize(); 

    return 0; 
} 

Sau khi biên dịch nó như sau:

$ mpicc -std=c99 simple_mpi.c -o simple_mpi 

Nó chạy và đưa ra này:

$ mpiexec -n 4 ./simple_mpi 
Process 0 received -2 from process 0 
Process 1 received -2 from process 0 
Process 3 received -2 from process 0 
Process 2 received -2 from process 0 
Process 0 received result 1 from process 0 
Process 0 received result 2 from process 1 
Process 0 received result 3 from process 2 
Process 0 received result 4 from process 3 
1

Trên thực tế, xử lý 1-3 thực sự đang gửi kết quả về bộ vi xử lý 0. Tuy nhiên, bộ xử lý 0 bị kẹt trong vòng lặp đầu tiên của vòng lặp này:

for(i=0; i<4; i++) 
{  
    MPI_Recv(&number, 1, MPI_INT, i, 99, MPI_COMM_WORLD, MPI_STATUS_IGNORE); 
    printf("Process 0 received number %d from i:%d\n", number, i); 
} 

Trong cuộc gọi MPI_Recv đầu tiên, bộ xử lý 0 sẽ chặn chờ để nhận tin nhắn từ thẻ 99, tin nhắn 0 chưa gửi.

Nói chung, một bộ xử lý gửi nhận/nhận tin nhắn cho chính nó là một ý tưởng tồi, đặc biệt khi sử dụng các cuộc gọi chặn. 0 đã có giá trị trong bộ nhớ. Nó không cần phải gửi nó cho chính nó.

Tuy nhiên, một cách giải quyết là để bắt đầu nhận được vòng lặp từ i=1

for(i=1; i<4; i++) 
{   
    MPI_Recv(&number, 1, MPI_INT, i, 99, MPI_COMM_WORLD, MPI_STATUS_IGNORE); 
    printf("Process 0 received number %d from i:%d\n", number, i); 
} 

Chạy mã bây giờ sẽ cung cấp cho bạn:

Process 1 received number -2 from process 0 
Process 2 received number -2 from process 0 
Process 3 received number -2 from process 0 
Process 0 received number 2 from i:1 
Process 0 received number 3 from i:2 
Process 0 received number 4 from i:3 
Process 0 received number -2 from process 0 

Lưu ý rằng việc sử dụng MPI_Bcast và MPI_Gather như đã đề cập bởi Gilles là một cách phân phối/thu thập dữ liệu hiệu quả hơn và tiêu chuẩn hơn nhiều.

Các vấn đề liên quan