Tôi có một mảng cấu trúc động trong C. giải thích:
int n=100;
hạt cấu trúc {
vị trí gấp đôi[3];
lực kép[3];
khối lượng gấp đôi;
kiểu int;
};
hạt cấu trúc *mypart;
mypart = (struct hạt*) calloc(n,sizeof(struct hạt));
Trong mã song song, một số thao tác được thực hiện trên mypart[i].force[j]
thực hiện trên mảng này và cuối cùng tôi cần thực hiện MPI_Allreduce (maypart[i] .force
) .bằng cách xem xét MPI_Type_create_struct
và các hàm data_type khác, tôi không thể có bất kỳ giải pháp hiệu quả nào để chỉ chuyển mảng bên trong cấu trúc sang các lõi khác. Có ai biết không?
Cập nhật: Một số chi tiết về mã: Đây là mã động lực phân tử trong đó lực tác dụng lên mỗi hạt là do tương tác với các hạt khác. Mục đích là để phân chia lực tính toán trên từng lõi. Lực tác dụng lên hạt thứ i có thể được tính đồng thời trên các hạt nhân khác nhau. Sau vòng lặp lực, các lực tác dụng lên hạt đó phải được tính tổng để có một lực có giá trị duy nhất (3 thành phần) trên mỗi hạt. Điều này được thực hiện thông qua hàm MPI_Allreduce + MPI_SUM. Tôi hy vọng điều này làm rõ những gì tôi đang cố gắng làm.
Những gì bạn muốn đạt được không phải là không thể nhưng cũng không hề tầm thường. Đầu tiên, bạn phải khai báo kiểu dữ liệu đại diện cho toàn bộ kiểu cấu trúc hoặc kiểu dữ liệu chỉ chứa các lực. Để xây dựng cái sau, hãy bắt đầu với ba lần tăng gấp đôi liên tiếp được dịch chuyển một cách thích hợp:
MPI_Datatype type_force;
int blen = 3;
MPI_Aint displ = offsetof(hạt cấu trúc, lực);
Loại MPI_Type = MPI_DOUBLE;
MPI_Type_create_struct(1, &blen, &displ, &types, &type_force);
Kiểu dữ liệu mới phải có kích thước phù hợp với phạm vi của cấu trúc C để chúng ta có thể truy cập trực tiếp vào nhiều phần tử mảng:
MPI_Datatype type_force_resized;
MPI_Aint lb, phạm vi;
MPI_Type_get_extent(type_force, &lb, &extent);
phạm vi = sizeof(hạt cấu trúc);
MPI_Type_create_resized(type_force, lb, phạm vi, &type_force_resized);
MPI_Type_commit(&type_force_resized);
Bây giờ giảm (tất cả) toàn cầuhầu hếtNó sôi sục đến:
hạt cấu trúc *hạt = calloc(n, sizeof(hạt cấu trúc));
MPI_Allreduce(mypart, hạt, n, type_force_resized,
MPI_SUM, MPI_COMM_WORLD);
由于 MPI_(Tất cả)Giảm
Không được phép sử dụng các kiểu dữ liệu MPI khác nhau cho bộ đệm nguồn và bộ đệm nhận, vì vậy một tập hợp hạt cấu trúc
thay vì chỉ gấp đôi[n][3]
. Kết quả sẽ được đặt trong từng phần tử mảng lực lượng []
trong lĩnh vực này.
Bây giờ, câu hỏi là MPI_SUM
Không có thao tác nào được thực hiện trên các kiểu dữ liệu dẫn xuất. Giải pháp là khai báo hoạt động giảm thiểu của riêng bạn:
void Force_sum(cấu trúc hạt *in, cấu trúc hạt *inout,
int *len, MPI_Datatype *dptr)
{
cho (int i = 0; i < *len; i++)
{
inout[i].force[0] += in[i].force[0];
inout[i].force[1] += in[i].force[1];
inout[i].force[2] += in[i].force[2];
}
}
MPI_Op lực_sum_op;
MPI_Op_create(force_sum, 1, &force_sum_op);
Với tất cả các chế phẩm trên, mức giảm sẽ trở thành:
MPI_Allreduce(mypart, hạt, n, type_force_resized,
lực_tổng_op, MPI_COMM_WORLD);
Một biến thể đơn giản hơn là nếu trước tiên bạn tập hợp tất cả các lực lại với nhau theo mộtlực lượng kép[n] [3]
trong mảng. Sau đó, toàn bộ hoạt động giảm thiểu sẽ diễn ra như sau:
lực lượng kép[n][3]; // Lực lượng cục bộ
tổng lực gấp đôi[n][3] // Tổng lực
... chuyển mypart[i].lực thành lực[i] ...
MPI_Allreduce(lực, tổng_lực, 3*n, MPI_DOUBLE,
MPI_SUM, MPI_COMM_WORLD);
// Xong
Tuy nhiên, phương pháp này chiếm thêm bộ nhớ và yêu cầu thao tác sao chép bộ nhớ.
Tôi là một lập trình viên xuất sắc, rất giỏi!