Đầu tiên, câu trả lời chính xác phụ thuộc vào: (1) cách sử dụng, tức là các đối số đầu vào chức năng, (2) chất lượng và chi tiết triển khai MPI và (3) phần cứng bạn đang sử dụng. Thông thường, (2) và (3) có liên quan, chẳng hạn như khi nhà cung cấp phần cứng tối ưu hóa MPI cho mạng của họ.
Nói chung, việc hợp nhất các tập hợp MPI sẽ tốt hơn cho các tin nhắn nhỏ hơn, vì chi phí khởi động có thể không cần thiết và việc đồng bộ hóa bằng cách chặn tập thể nên được giảm thiểu nếu có sự khác biệt về thời gian tính toán giữa các cuộc gọi. Đối với các tin nhắn lớn hơn, mục tiêu nên là để giảm thiểu lượng dữ liệu được gửi.
Ví dụ, về lý thuyết, MPI_Reduce_scatter_block
nên tốt hơn so với MPI_Reduce
theo sau MPI_Scatter
, mặc dù cái trước thường được thực hiện theo nghĩa sau, vì vậy không có lợi thế thực sự. Có một mối tương quan giữa chất lượng thực hiện và tần suất sử dụng trong hầu hết các triển khai MPI và các nhà cung cấp rõ ràng tối ưu hóa các chức năng mà hợp đồng máy này yêu cầu.
Mặt khác, nếu một người MPI_Reduce_scatter_block
sử dụng Blue Gene, thì việc sử dụng MPI_Allreduce
, giao tiếp nhiều hơn MPI_Reduce
và MPI_Scatter
kết hợp, thực sự nhanh hơn một chút. Đây là điều mà tôi mới phát hiện ra và là một sự vi phạm thú vị về nguyên tắc tự thống nhất hiệu suất trong MPI (nguyên tắc này được mô tả chi tiết hơn trong "Nguyên tắc thực hiện MPI tự thống nhất" ).
Trong trường hợp cụ thể của phân tán + thu thập so với phân phối, hãy xem xét rằng trước đây, tất cả dữ liệu phải được chuyển đến và từ một quy trình duy nhất, điều này làm cho nó bị nghẽn cổ chai, trong khi đó, tất cả các dữ liệu có thể chảy vào và ra khỏi tất cả các cấp bậc ngay lập tức , bởi vì tất cả các cấp bậc có một số dữ liệu để gửi cho tất cả các cấp bậc khác. Tuy nhiên, gửi dữ liệu từ tất cả các nút cùng một lúc không nhất thiết là một ý tưởng hay trên một số mạng.
Cuối cùng, cách tốt nhất để trả lời câu hỏi này là làm như sau trong mã của bạn và trả lời câu hỏi bằng thí nghiệm.
#ifdef TWO_MPI_CALLS_ARE_BETTER_THAN_ONE
MPI_Scatter(..)
MPI_Gather(..)
#else
MPI_Allgather(..)
#endif
Một tùy chọn thậm chí tốt hơn là để mã của bạn đo lường bằng thực nghiệm trong hai lần lặp đầu tiên, sau đó sử dụng cái nào nhanh hơn cho các lần lặp còn lại:
const int use_allgather = 1;
const int use_scatter_then_gather = 2;
int algorithm = 0;
double t0 = 0.0, t1 = 0.0, dt1 = 0.0, dt2 = 0.0;
while (..)
{
if ( (iteration==0 && algorithm==0) || algorithm==use_scatter_then_gather )
{
t0 = MPI_Wtime();
MPI_Scatter(..);
MPI_Gather(..);
t1 = MPI_Wtime();
dt1 = t1-t0;
}
else if ( (iteration==1 && algorithm==0) || algorithm==use_allgather)
{
t0 = MPI_Wtime();
MPI_Allgather(..);
t1 = MPI_Wtime();
dt2 = t1-t0;
}
if (iteration==1)
{
dt2<dt1 ? algorithm=use_allgather : algorithm=use_scatter_then_gather;
}
}
MPI_Scatter
theo sauMPI_Gather
không cung cấp cùng một ngữ nghĩa giao tiếp nhưMPI_Allgather
. Có lẽ có sự dư thừa liên quan khi bạn thể hiện hoạt động theo một trong hai cách?