1 Giới thiệu
MPI là viết tắt của Giao diện truyền tin nhắn. Một triển khai MPI như MPICH" hoặc OpenMPI được sử dụng để tạo ra một nền tảng để viết các chương trình song song trong một hệ thống phân tán như cụm Linux có bộ nhớ phân tán. Nhìn chung, nền tảng được xây dựng cho phép lập trình bằng C sử dụng chuẩn MPI. Vì vậy, để chạy các chương trình song song trong môi trường này bằng python, chúng ta cần sử dụng một mô-đun có tên là MPI4py có nghĩa là "MPI cho Python". Mô-đun này cung cấp các hàm chuẩn để thực hiện các tác vụ như lấy thứ hạng của bộ xử lý, gửi và nhận tin nhắn/dữ liệu từ nhiều nút khác nhau trong cụm. Nó cho phép chương trình được thực thi song song với các tin nhắn được truyền giữa các nút. Điều quan trọng là MPIch2 và MPI4py được cài đặt trong hệ thống của bạn. Vì vậy, nếu bạn chưa cài đặt MPI4Py, sau đây là 2 hướng dẫn để tham khảo để cài đặt, xây dựng và thử nghiệm một chương trình mẫu trong MPI4PY.
Mã:
https://seethesource.wordpress.com/2015/01/05/raspberypi-hacks-part1/https://seethesource.wordpress.com/2015/01/14/raspberypi-hacks-part2/
2 Gửi và nhận tin nhắn
Giao tiếp trong mpi4py được thực hiện bằng cách sử dụng phương thức send() và recv(). Như tên gọi của nó, nó được sử dụng để gửi và nhận tin nhắn từ các nút tương ứng.2.1 Giới thiệu về send()
Cú pháp chung của hàm này là: comm.send(data,dest)trong đó "data" có thể là bất kỳ dữ liệu/tin nhắn nào phải được gửi đến một nút khác và "dest" biểu thị thứ hạng quy trình của các nút cần gửi đến.
Ví dụ: comm.send((rank+1)*5,dest=1).Điều này sẽ gửi tin nhắn "(rank+1)*5" đến nút có thứ hạng quy trình=1. Vì vậy, chỉ có nút đó mới có thể nhận được nó.
2.2 Giới thiệu về recv()
Cú pháp chung của hàm này là: comm.recv(source)Điều này cho biết một quy trình cụ thể chỉ nhận dữ liệu/tin nhắn từ quy trình có thứ hạng được đề cập trong tham số "source".
Ví dụ: comm.recv(source=1)Điều này chỉ nhận tin nhắn từ một quy trình có thứ hạng=1.
2.3 Ví dụ với send() và recv() đơn giản
Mã:
if rank==0 : data= (rank+1)*5 comm.send(data,dest=1)if rank==1: data=comm.recv(source-0) print data
[Tải xuống Example1.py]
2.4 Lưu ý
- Khi một nút đang chạy phương thức recv(), nó sẽ đợi cho đến khi nhận được một số dữ liệu từ nguồn mong đợi. Sau khi nhận được một số dữ liệu, nó tiếp tục với phần còn lại của chương trình.
- Ở đây, tham số "dest" trong send() và tham số "source" trong recv() không chỉ cần có một giá trị hằng số (hoặc thứ hạng), nó có thể là một biểu thức.
- Thành viên "size" của đối tượng "comm" là một cách tốt để điều kiện hóa các phương thức send() và receive() và điều này dẫn chúng ta đến việc gửi và nhận tin nhắn động.
2.5 Gửi và nhận động
Truyền dữ liệu động hữu ích hơn nhiều vì nó cho phép nhiều nút gửi và nhận dữ liệu cùng một lúc và quyết định truyền có thể được thực hiện tùy thuộc vào các tình huống cụ thể và do đó điều này làm tăng đáng kể tính linh hoạt.2.6 Ví dụ về việc gửi và nhận động của data
Mã:
comm.send(data_shared,dest=(rank*2)%size)comm.recv(source=(rank-3)%size)
(để biết thêm về triển khai đầy đủ, hãy tham khảo Example2.py)
[Tải xuống Example2.py]
3 hàm send() và recv() được gắn thẻ
Khi chúng ta gắn thẻ send() và recv(), chúng ta có thể đảm bảo thứ tự nhận thông điệp, do đó chúng ta có thể chắc chắn rằng một thông điệp sẽ được gửi trước thông điệp khácTrong quá trình truyền dữ liệu động, sẽ phát sinh các tình huống mà chúng ta cần một send() cụ thể để khớp với một recv() cụ thể để đạt được một loại đồng bộ hóa. Điều này có thể được thực hiện bằng cách sử dụng tham số "tag" trong cả send() và recv().
Ví dụ, send() có thể trông như sau: comm.send(shared_data,dest=2,tag=1) và một recv() khớp với câu lệnh trên sẽ trông như sau: comm.recv(source=1,tag=1)
Vì vậy, cấu trúc này buộc phải khớp, dẫn đến đồng bộ hóa các lần truyền dữ liệu. Ưu điểm của việc gắn thẻ là recv() có thể được thực hiện để đợi cho đến khi nhận được dữ liệu từ send() tương ứng với thẻ mong đợi. Tuy nhiên, điều này phải được sử dụng hết sức cẩn thận vì nó có thể dẫn đến trạng thái bế tắc.
3.1 Ví dụ
Mã:
Nếu rank==0: shared_data1 = 23 comm.send(shared_data1,dest=3,tag=1) shared_data2 = 34 comm.send(shared_data2,dest=3,tag=2) Nếu rank==3: recv_data1 = comm.recv(source=0,tag=2) print recv_data1 recv_data2 = comm.recv(source=0,tag=1) print recv_data2
Mã:
3423
(Để biết đầy đủ các triển khai, hãy tham khảo Example3.py)
[Tải xuống Example3.py]
4 Phát sóng
Phát sóng cho phép người dùng thêm thuộc tính động vào lập trình song song, trong đó, một số dữ liệu được tạo bởi máy chủ chính một lần có thể được phát sóng đến tất cả các nút. Điều này tránh được quy trình lặp đi lặp lại để gửi dữ liệu đến từng nút. Từ nút master/root, chúng ta tạo dữ liệu từ nút này và gửi đến tất cả các nút khác.4.1 Ví dụ
Mã:
if rank == 0 data = {'a':1,'b':2,'c':3} else data = None data = comm.bcast(data,root=0) print "rank", rank, data
Mã:
rank 0 {'a':1,'b':2,'c':3}rank 4 {'a':1,'b':2,'c':3}rank 3 {'a':1,'b':2,'c':3}rank 1 {'a':1,'b':2,'c':3}hạng 2 {'a':1,'b':2,'c':3}
5 Phân tán
Phân tán là quá trình chia nhỏ dữ liệu và gửi hoặc phân phối từng phần đến một nút khác nhau. Ví dụ là chia nhỏ một danh sách và gửi từng phần tử danh sách đến một nút khác nhau.5.1 Ví dụ
Mã:
comm = MPI.COMM_WORLD size=comm.get_size() rank-comm.get_rank() if rank == 0: data = [(x+1) ** x for x in range (size)] print 'scattering data',data else: data = None data = comm.scatter(data,root=0) print 'rank',rank,'has data: ', data
Mã:
scattering data : [1,2,9,64,625]hạng 0 có dữ liệu: 1hạng 1 có dữ liệu: 2hạng 2 có dữ liệu: 9hạng 3 có dữ liệu: 64hạng 4 có dữ liệu: 625
6 Gather
Gather là đối lập của scatter. Nó được sử dụng để thu thập dữ liệu từ nhiều nút khác nhau và lưu trữ chúng thành một. Một ví dụ là thu thập các phần tử từ nhiều nút khác nhau và tạo một danh sách duy nhất từ những phần tử đó.6.1 Ví dụ
Ví dụ: (Xin lưu ý rằng ví dụ này giống với ví dụ trước về scatter nhưng có một vài bổ sung)
Mã:
comm = MPI.COMM_WORLD size=comm.get_size() rank-comm.get_rank() if rank == 0: data = [(x+1) ** x for x in range (size)] print 'scattering data',data else: data = None data = comm.scatter(data,root=0) print 'rank',rank,'has data: ', data new_data = comm.gather(data, root=0) if rank == 0: print 'master collected: ', new_data
Mã:
rank 0 has data : 1rank 1 có dữ liệu: 2hạng 2 có dữ liệu: 9hạng 3 có dữ liệu: 64hạng 4 có dữ liệu: 625chủ thu thập: [ 1, 2, 3, 9,64, 625]
7 Kết luận
Bài đăng này đã giới thiệu và sử dụng nhiều cấu trúc lập trình khác nhau của mpi4py sẽ giúp bạn viết các chương trình song song cho môi trường phân tán bằng ngôn ngữ lập trình python. Mặc dù đây là các cấu trúc riêng lẻ được hiển thị ở trên trong hầu hết các chương trình, tất cả hoặc hầu hết chúng đều được sử dụng cùng nhau. Tôi muốn chia sẻ một số ứng dụng có thể được xây dựng bằng mpi4py.- Tóm tắt văn bản tự động
- - một nhánh của Xử lý ngôn ngữ tự nhiên, trong đó một chương trình phân tán có thể được viết để tóm tắt nhiều tài liệu văn bản cùng một lúc
- Sắp xếp và tìm kiếm - môi trường phân tán có thể được sử dụng bằng cách chia nhỏ dữ liệu cần sắp xếp hoặc tìm kiếm để có thể xử lý một lượng lớn dữ liệu trong một khoảng thời gian ngắn.
- Các giải pháp toán học - chẳng hạn như phân phối chất độc có thể được giải quyết nhanh hơn nhiều trong môi trường song song