2012-11-09 36 views
24

Tôi tự hỏi khi nào tôi cần sử dụng rào cản? Tôi có cần nó trước/sau khi phân tán/thu thập chẳng hạn? Hoặc OMPI nên đảm bảo tất cả các quy trình đã đạt đến điểm đó trước khi phân tán/thu thập? Tương tự, sau khi phát sóng, tôi có thể mong đợi tất cả các quy trình đã nhận được tin nhắn không?Khi nào tôi cần sử dụng MPI_Barrier()?

Trả lời

21

Tất cả các hoạt động tập thể trong MPI trước khi MPI-3.0 đang chặn, điều đó có nghĩa là sử dụng tất cả bộ đệm được truyền cho chúng sau khi chúng trở về an toàn là an toàn. Đặc biệt, điều này có nghĩa là tất cả dữ liệu đã được nhận khi một trong các hàm này trả về. (Tuy nhiên, nó không ngụ ý rằng tất cả các dữ liệu đã được gửi!) Vì vậy, MPI_Barrier là không cần thiết (hoặc rất hữu ích) trước/sau khi hoạt động tập thể, nếu tất cả các bộ đệm là hợp lệ rồi.

Cũng xin lưu ý rằng MPI_Barrier không kỳ diệu chờ các cuộc gọi không chặn. Nếu bạn sử dụng một gửi/recv không chặn và cả hai quá trình chờ đợi tại một MPI_Barrier sau khi gửi/recv cặp, nó không được đảm bảo rằng các quá trình gửi/nhận được tất cả dữ liệu sau khi MPI_Barrier. Sử dụng MPI_Wait (và bạn bè) để thay thế. Vì vậy, đoạn mã sau đây có lỗi:

/* ERRORNOUS CODE */ 

Code for Process 0: 
Process 0 sends something using MPI_Isend 
MPI_Barrier(MPI_COMM_WORLD); 
Process 0 uses buffer passed to MPI_Isend // (!) 

Code for Process 1: 
Process 1 recvs something using MPI_Irecv 
MPI_Barrier(MPI_COMM_WORLD); 
Process 1 uses buffer passed to MPI_Irecv // (!) 

Cả hai dòng được đánh dấu bằng (!) đều không an toàn!

MPI_Barrier chỉ hữu ích trong một số ít trường hợp. Hầu hết thời gian bạn không quan tâm liệu các quy trình của bạn có đồng bộ hóa hay không. Đọc tốt hơn về chặn và cuộc gọi không chặn!

+0

Tại sao lỗi 1 (!) 'Thứ nhất? Quy trình 0 vẫn sẽ có bộ đệm riêng của nó? Cũng kể từ khi gửi của nó, bên nhận sẽ không thay đổi nó phải không? –

+2

@JiewMeng MPI không được đọc từ bộ đệm ngay sau khi bạn gọi MPI_Isend. Nếu bạn thay đổi nó tại '(!)', Bạn có thể gửi một cái gì đó khác nhau. Tôi không hoàn toàn chắc chắn về nó, nhưng tôi nghĩ rằng hành vi là không xác định trong trường hợp này. –

+3

Tôi đã cập nhật một chút câu trả lời của bạn vì MPI-3.0 đã giới thiệu các tập thể không chặn. –

13

Một lần sử dụng MPI_Barrier là ví dụ để kiểm soát quyền truy cập vào tài nguyên bên ngoài, chẳng hạn như hệ thống tệp, không được truy cập bằng MPI. Ví dụ, nếu bạn muốn mỗi quá trình để viết thứ vào một tập tin theo thứ tự, bạn có thể làm điều đó như thế này:

int rank, size; 
MPI_Comm_rank(MPI_COMM_WORLD, &rank); 
MPI_Comm_size(MPI_COMM_WORLD, &size); 
for (int ii = 0; ii < size; ++ii) { 
    if (rank == ii) { 
     // my turn to write to the file 
     writeStuffToTheFile(); 
    } 
    MPI_Barrier(MPI_COMM_WORLD); 
} 

Bằng cách đó, bạn có thể chắc chắn rằng không có hai quá trình đang đồng thời kêu gọi writeStuffToTheFile.

0

Có thể không sử dụng MPI_Barrier(), nhưng nó rất hữu ích. Thực tế, ngay cả khi bạn đang sử dụng giao tiếp đồng bộ, MPI_Send/Recv() chỉ có thể đảm bảo hai quy trình được đồng bộ hóa. Trong dự án của tôi, một dự án cuda + MPI, tất cả những gì tôi sử dụng là giao tiếp không đồng bộ. Tôi thấy rằng trong một số trường hợp nếu tôi không sử dụng MPI_Barrier() theo sau bởi hàm Wait(), tình huống hai quá trình (gpu) muốn truyền dữ liệu cho nhau cùng một lúc rất có thể xảy ra, có thể làm giảm hiệu quả chương trình. Lỗi trên bao giờ làm tôi điên và mất một vài ngày để tìm nó. Vì vậy bạn có thể suy nghĩ cẩn thận cho dù sử dụng MPI_Barrier() khi bạn sử dụng MPI_Isend/Irecv trong chương trình của bạn. Đôi khi đồng bộ hóa các quy trình không chỉ cần thiết mà còn PHẢI, đặc biệt là chương trình ur đang xử lý thiết bị.