Các mô hình lập trình song song
Chương 2: Các mơ hình lập trình song song I Giới thiệu - Mơ hình chia sẻ nhớ - Mơ hình nhớ phân tán: - Các cơng cụ lập trình song song Bộ nhớ chung Bộ nhớ phân tán Công cụ hệ thống Threads (pthread) Sockets Công cụ chuyên biệt OpenMP Pthread MPI PVM Globus Toolkit (GT4) - Mơ hình trao đổi liệu: Trao đổi liệu thông qua truyền thông điệp Trao đổi liệu thơng qua nhớ chung -1- II Lập trình chia sẻ nhớ Giả thiết có hệ thống đa xử lý đối xứng SMP Đó hệ thống tất xử lý nhau, khơng có xử lý đặc biệt để xử lý vào/ra, khơng có xử lý gán cho nhiệm vụ đặc biệt khác Đây mơ hình chung cho hệ thống đa xử lý Để nghiên cứu song song, khơng thiết phải có hệ đa xử lý mức vật lý Trong môi trường UNIX, WINDOWS tạo nhiều tiến trình khác hệ thống chúng sử dụng để mô lập trình đa xử lý Trong lập trình thủ tục (như với C, C++, Pascal, Fortran), ta mơ tả tốn cách độc lập với ngơn ngữ lập trình Khi có mơ tả thuật tốn ta dễ dàng cài đặt ngơn ngữ lập trình khác hầu hết ngơn ngữ lập trình thủ tục sử dụng lệnh cấu trúc điều khiển chuẩn như: tuần tự, rẽ nhánh if-then, cấu trúc lặp (for, while, repeat), v.v Tương tự vậy, mơi trường lập trình chia sẻ nhớ có hai ràng buộc quan trọng mà phải ý: (i) Một tiến trình chờ khoảng thời gian hai câu lệnh cần thực Giả sử xử lý P thực chương trình có 100 câu lệnh, xử lý Q thực chương trình có 10 câu lệnh bắt đầu thực Thậm chí, tất câu lệnh có tốc độ thực khơng thể nói Q kết thúc trước P (ii) Không thể xem lệnh thực đơn thể mức ngơn ngữ lập trình Ví dụ, lệnh đơn giản như: a = a + b dãy lệnh ngôn ngữ máy Mà ta biết rằng, tiến trình hệ điều hành nhận biết câu lệnh ngơn ngữ máy Lập trình chia sẻ nhớ dựa vào tiến trình Yêu cầu xử lý song song phải tạo số tiến trình cần thiết cho tốn khả huỷ bỏ chúng phần việc xử lý song song kết thúc để giải phóng nhớ thiết bị mà tiến trình chiếm giữ Việc huỷ bỏ tiến trình phải khơng cản trở hoạt động tiến trình khác VD: Cấu trúc chương trình có N tiến trình song song Tạo N tiến trình: id = create_process(N); => Ta có N+1 tiến trình (một tiến trình chủ) Phân cơng nhiệm vụ cho tiến trình: id = create_process(N); switch(id) { -2- case 1: … NhiemVu1 …(s1); break; case 2: … NhiemVu2 …(s2); break; case N: … NhiemVuN …(sn); break; } Thu nhận kết tính tốn: join_process(N, 0); // Các lệnh phải chờ s=0; For (i=1,n) s=s+si; Tiến trình chủ thu thập kết tính tốn tiến trình khác thực cơng việc cịn lại, cịn tiến trình khác kết thúc Khi viết join_process(N, id);id tiến trình cịn tiếp tục hoạt động Nếu ta đặt sau số câu lệnh thì: § Các câu lệnh không thực tất tiến trình thực join_process() § Sau cịn lại tiến trình chủ hoạt động Cách thức trao đổi liệu tiến trình: Một mặt tiến trình muốn giữ phần liệu cục cho riêng mình, khơng cho tiến trình khác nhìn thấy/truy cập tới liệu Mặt khác, muốn trao đổi thơng tin với tiến trình khác Xử lý vấn đề che giấu hay chia sẻ thông tin cịn tuỳ thuộc vào mơ hình mà áp dụng, dựa vào tiến trình hay luồng § Các tiến trình UNIX, WINDOWS sử dụng đơn vị tính tốn độc lập Khi muốn sử dụng nhớ chung, ta cần phải xin cấp phát nhớ sau sử dụng xong phải giải phóng chúng Người lập trình phải có trách nhiệm giải phóng nhớ chia sẻ cách tường minh chúng không cịn cần thiết sử dụng Có hai hàm sở: o shared(m, &id): cấp phát m byte nhớ chia sẻ cho tiến trình id o free_shm(): giải phóng nhớ cấp § Đối với luồng, tất thơng tin, theo mặc định, nhìn thấy Do vậy, mơ hình cần phải cố gắng để che giấu thơng tin Ví dụ: Cho trước đoạn chương trình tính tổng hai vector: for(i = 0; i < N; i++){ // (1) C[i] = A[i] + B[i]; } Thực song song hoá đoạn chương trình nào? -3- Tương tự ví dụ nêu trên, giả sử ta có M tiến trình Chúng ta chia N phần tử thành M phần (thường ta giả thiết N chia hết cho M) gán phần cho tiến trình Chu trình viết thành: for(j = id * N/M; j < (id+1)*N/M; j++){ C[j] = A[j] + B[j]; } Trong đó, id số hiệu tiến trình, chạy từ đến M-1 Tiến trình thứ i xử lý N/M phần tử liên tiếp kể từ i*N/M+1, ví dụ hình 3-1 (a) Hoặc ta cho phép tiến trình truy cập xen kẽ vào phần tử mảng sau: Tiến trình Pi phần tử thứ i, sau bỏ qua M phần tử để xử lý phần từ tiếp theo, nghĩa truy cập đến i, i+M, i+2M, v.v., ví dụ hình 3-1 (b) Chu trình (1) viết sau: for(j = id; j < N; j+=M){ C[j] = A[j] + B[j];} Ví dụ: Khi N = 15 M = việc gán phần tử vector cho tiến trình thực theo cách sau: P1 P2 P3 P4 P5 P1 P2 P3 P4 P5 11 12 10 13 11 14 12 15 (a) 10 13 14 15 (b) Hình 3- Các cách phân chia chu trình mảng Lập trình chia sẻ nhớ dựa vào luồng (thread) Các luồng tiến trình chia sẻ với không gian địa chương trình, đoạn liệu mơi trường xử lý, đồng thời có vùng liệu riêng để thao tác Các tiến trình luồng hệ thống song song cần phải đồng bộ, song việc đồng luồng thực hiệu đổi với tiến trình Đồng tiến trình địi hỏi tốn thời gian hoạt động hệ thống, luồng việc đồng chủ yếu tập trung vào truy cập biến chung (global) chương trình Nhiều hệ điều hành hỗ trợ đa luồng như: SUN Solaris, Window NT, Windows 2000, OS/2, v.v Hiện có chuẩn cho việc lập trình song song dựa luồng Pthread IEEE Portable Operating System Interface, POSIX -4- III Tính tốn song song phân tán: mơ hình gửi/nhận thơng báo (cluster computing, Grid computing) Tính tốn phân tán tính tốn thực sở kết hợp khả tính tốn truyền thơng hai hay nhiều máy tính mạng Mơ hình tính tốn phân tán có ưu điểm sau: § Cho phép chia sẻ liệu lưu trữu nhiều máy tính khác § Chia sẻ với số chức máy tính § Độ tin cậy cao Trong trường hợp có máy tính bị trục trặc máy tính khác thay để hồn thành nhiệm vụ hệ thống § Tính kinh tế: thường đầu tư vào hệ phân tán thấp đầu tư cho hệ tập trung Tuy nhiên, hệ tính tốn phân tán đứng trước nhiều thách thức: + Những vấn đề liên quan đến việc quản trị hệ thống, vấn đề đảm bảo an tồn hệ thống, bảo mật thơng tin, v.v + Xử lý hệ thống phân tán khơng có nhớ chia sẻ để trao đổi liệu với Sự trao đổi thực cách gửi/nhận thơng báo Hiện có nhiều cơng cụ lập trình sử dụng cho tính tốn phân tán nhiều mức độ trừu tượng khác nhau, như: PVM, MPI, Globus Toolkit v.v 1) Mơ hình gửi/nhận thơng báo Giống mơ hình chia sẻ nhớ, đơn vị xử lý song song mơ hình gửi/nhận thơng báo tiến trình Tuy nhiên có số điểm khác hai mơ hình này, mơ hình gửi/nhận thơng báo: § Các tiến trình thực xử lý khác không truy cập vào không gian nhớ chia sẻ § Các tiến trình phân tán trao đổi liệu với qua hệ thống mạng cục mạng diện rộng Việc truyền thông đồng hố hoạt động tiến trình thực thông qua hai phương thức send() receive() § Tất biến cục tiến trình Vì thế, vấn đề xung đột liệu (cần phải khoá liệu tiến trình truy cập), hay tranh chấp thơng tin (bài tốn loại trừ nhau) khơng xuất mơ hình tính tốn phân tán Nói chung có hai mơ hình gửi/nhận thơng báo: § Gửi/nhận thơng báo theo chế dị bộ: Trong mơ hình này, kênh truyền thơng giả thiết có khả tiếp nhận khơng bị giới hạn Khả không giới hạn cài đặt thực tế cách sử dụng đệm (buffer) để tiếp nhận thông điệp gửi đến cho tiến trình Do vậy, tiến trình gửi khơng phải chờ tiến trình nhận sẵn sàng nhận mà gửi có liệu Ở đây, hai tiến trình gửi nhận hoạt động gần đọc lập với thơng điệp nhận -5- sau khoảng thời gian (lâu bất kỳ) kể từ gửi Tuy nhiên, tiến trình nhận muốn nhân liệu phải chờ có thơng điệp tiến trình khác gửi cho Có số yêu cầu sau truyền thơng di bộ: o Khi tiến trình A gửi thơng điệp cho tiến trình B sau cần phải biết xem B có nhận hay không, nghĩa A phải chờ để nhận câu trả lời khẳng định B Việc phân phát thông điệp đảm bảo không bị thất bại Nếu A gửi thông điệp cho B A không nhận câu trả lời từ B khơng biết thơng điệp gửi đến đích B hay chưa? (có thể tiến trình B khơng nhận câu trả lời B không đến A) o Tất thông điệp phải đưa vào đệm (hàng đợi), thực tế không gian hàng đợi hữu hạn Khi có q nhiều thơng điệp gửi phương thức gửi bị chặn lại Điều vi phạm ngữ nghĩa mơ hình gửi/nhận thơng báo dị § Gửi/nhận thơng báo theo chế đồng bộ: Trong mơ hình này, tiến trình gửi bị chặn lại tiến trình nhận sẵn sàng nhận Ở đây, truyền thông đồng hố ln gắn chặt với Hệ thống gửi/nhận thơng báo đồng hoàn toàn giống hệ thống điện thoại, kênh truyền thơng bị chặn lại q trình đàm thoại Hệ truyền thông dị lại giống với hệ thống bưu chính, người nhận phải chờ có thư gửi đến Chúng ta phân tích thêm để hiểu rõ phát triển hai mơ hình *) Cơ chế gửi/nhận thơng báo đồng bộ: Ưu điểm: Làm cho nhiều vấn đề đồng hoá việc cấp phát nhớ động trở lên đơn giản Nhược điểm: - Việc gắn chặt tiến trình với thời gian phân phát thơng điệp xem điều kiện ràng buộc bổ sung đòi hỏi thiết kế thực thi chương trình - Việc bắt tiến trình gửi phải chờ dẫn đến việc làm giảm tính đồng thời hệ thống - Ngoài ra, để cài đặt hiệu hệ thống truyền thơng đồng địi hỏi phải có phần cứng đặc biệt để đảm bảo truyền thông phải cực nhanh trao đổi liệu khơng ảnh hưởng tới tính tốn hệ thống Mà mạng truyền thơng nhanh có nhiều nút mạng trao đổi liệu với đắt tiền Vì lý trên, nên hệ gửi/nhận thơng báo dị làm việc mạng cục phát triển mạnh mẽ Các mơ hình lập trình dựa chế gửi/nhân thơng báo dị § Các yêu cầu trả lời qua lại khách (Client) chủ (Server) – Mơ hình hướng tâm: Mơ hình hay gặp Đây mơ hình mà máy tính có quan hệ gửi-nhận liệu với máy máy “chủ” Trong suốt q trình tính tốn, chúng khơng cần đến -6- Để cho rõ hơn, trình bày tư tưởng phân chia miền dựa vào ví dụ lấy tích π/2 phân hàm số ∫ cos(x)dx π/2 π/4 π/2 Do π/4 ∫ cos(x)dx = ∫ cos(x)dx + ∫ cos(x)dx mà sử dụng máy tính chạy song song Máy thứ tính giá trị π/4 π/2 π/4 ∫ cos(x)dx , máy thứ hai tính giá trị ∫ cos(x)dx Cuối máy chủ cộng kết § Mơ hình “đường-ống” Mơ hình đường ống mơ hình máy tính hình dung xếp thành hàng máy tính gửi nhận liệu cho máy kề bên § Mơ hình “vịng-trịn” Mơ hình vịng trịn mơ hình máy tính hình dung xếp thành hàng máy tính gửi nhận liệu cho máy kề bên Ngồi cịn có mơ hình: Hình sao, lưới 2D, lưới 3D, … Lập trình song song phân tán Lập trình theo mơ hình gửi/nhận thơng báo hệ thống nhiều máy tính thực theo ba cách: Cách 1: Sử dụng ngơn ngữ lập trình song song đặc biệt, ví dụ Occam thiết kế để sử dụng với Transputer (Inmos 1986) Cách 2: Sử dụng ngôn ngữ lập trình bậc cao (tuần tự) mở rộng cách bổ sung thêm từ khoá cú pháp mở rộng để xử lý việc trao đổi thông điệp, ví dụ CC++ (mở rộng C++) -7- Cách 3: Sử dụng ngơn ngữ lập trình bậc cao thư viện gồm thủ tục xử lý việc trao đổi thơng điệp, ví dụ ngơn ngữ C/C++ hệ chương trình thư viện để chạy với PVM, MPI, … Sau tập trung vào cách thứ ba Trong hệ thống trao đổi thơng điệp vấn đề tạo lập tiến trình để thực xử lý khác việc gửi, nhận thông điệp quan trọng Các bước xây dựng chương trình tính tốn song song sở trao đổi thơng báo Bước 1: Tạo tiến trình Một chức quan trọng lập trình song song tạo lập nhiều tiến trình để thực cơng việc chương trình song song Nói chung, chương trình bắt đầu thực tiến trình sau phát sinh nhiều tiến trình để khai thác khả song song tốn Có hai cách tạo lập tiến trình: tạo lập tĩnh tạo lập động § Tạo lập tiến trình tĩnh: số tiến trình xác định trước thực Trong hệ thống thường có tiến trình điều khiển cịn gọi tiến trình “chủ” (master), tiến trình khác gọi tiến trình tớ (slave) Đây mơ hình SPMD – có đoạn mã chung cho tất tiến trình Sau chương trình nguồn viết với lệnh phân chia cơng việc cho tiến trình, dịch sang mã thực thi cho tiến trình Q trình mơ tả hình 3-4 Chương trình nguồn Biên dịch theo xử lý Đoạn chương trình thực thi Đoạn chương trình thực thi BXL BXL n-1 Hình: Dịch đơn chương trình, đa thao tác liệu Ví dụ điển hình hệ thư viện MPI xây dựng theo cách tạo lập tĩnh § Tạo lập tiến trình động: Các tiến trình tạo lập bị huỷ bỏ có điều kiện số lượng tiến trình thay đổi q trình thực Mơ hình cho phép thực tạo lập động MPMD (MIMD), chương trình khác thực xử lý khác -8- Bước 2: Trao đổi liệu tiến trình thơng qua hàm send() receive() Việc gửi thông điệp thực cách xác định địa hay tất tiến trình nhận theo kênh truyền thơng Để lựa chọn thơng điệp, tiến trình nhận dựa vào tiến trình gửi, kênh truyền thơng, hay thẻ (tag) thơng điệp, v.v Có dạng gửi/nhận sau: Gửi thơng điệp cho tiến trình id: send(id: int, message: message_type); send(id: int, tag: int, message: message_type); Gửi thông điệp tới kênh truyền thông: thông điệp gửi cho tất tiến trình kênh mych (my channel) send(mych: channel, message: message_type); Nhận thông điệp từ kênh: để nhận thơng điệp chờ đợi từ kênh sử dụng lời gọi hàm sau: receive(mych: channel, message: message_type); Nhận từ địa nguồn: receive(source_id: int, msg: message_type); Nếu thông điệp ghi thẻ tiến trình nhận phân loại thơng điệp hộp nhận chọn thông điệp theo thẻ xác định receive(id: int, tag: int, msg: message_type); Ví dụ: send(dest_id, &x ); tiến trình nguồn gọi receive(source_id, &y); tiến trình đích để gửi giá trị liệu x từ tiến trình nguồn (source-id) sang biến y cho tiến trình đích Tất nhiên x, y phải có kiểu (kiểu tương thích với nhau) kích cỡ Tiến trình Tiến trình x send(2, &x); y receive(1, &y); Hình : Sự trao đổi thơng điệp hai tiến trình -9- Như phân tích, việc gửi nhận thơng điệp thực cách đồng dị Trong mô hình dị thơng điệp gửi đưa vào đệm để sau gửi dần tới cho tiến trình đích Để linh hoạt cho việc trao đổi, người ta thường gán cho thơng điệp thẻ (tag) sử dụng để phân biệt thơng điệp q trình trao đổi Một số vấn đề lập trình song song phân tán 3.1 Truy vấn kênh Nếu tiến trình gửi bị ngừng họat động thơng điệp gửi không đến hộp thư người nhận tiến trình nhận bị chặn lại để chờ mãi (dẫn đến tình trạng treo máy) Để xử lý vấn đề này, hầu hết chương trình thư viện cung cấp hàm truy vấn để biết trạng thái kênh Lời gọi receive() thực có thơng điệp chờ kênh truyền thơng Ngược lại, tiến trình thực công việc khác Để thực công việc trên, sử dụng hàm sau: Kiểm tra xem kênh có thơng điệp gửi đến cho tiến trình hay khơng? empty(ch: channel); Hàm gọi để xác định xem thơng điệp có kênh có phải gửi từ tiến trình id có thẻ tag? probe(id: int, tag: int);//id - tiến trình nhận - 10 - 3.2 Truyền thơng theo nhóm Nhiều chương trình phân tán cần phát tán nhận liệu từ nhiều tiến trình phân tán, nghĩa cần trao đổi với nhóm chương trình song song Để thực truyền thơng theo nhóm, sử dụng hàm: Broadcast(): phát tán thơng điệp cho tất tiến trình kênh mych Broadcast(mych:channel,tag:int, msg:message_type); Hoạt động lệnh Broadcast() mơ tả hình 3-6 Các tiến trình tham gia trao đổi phát tán liệu phải xác định Trong hình 3-6, tiến trình số xem tiến trình gốc chứa liệu mảng buf để phát tán cho tiến trình khác Theo qui ước mơ hình SPMD, tiến trình thực chương trình nên hình 3-6 tất tiến trình gọi hàm Broadcast() Hành động phát tán liệu không thực tất tiến trình thực lời gọi Broadcast() Tiến trình Dữ liệu Tiến trình n-1 Tiến trình Dữ liệu Dữ liệu buf Broadcast(); Broadcast(); Broadcast(); Hình 3-6 Hoạt động phát tán liệu Reduce(): thực phép tốn số học/logic nhóm tiến trình gửi kết tới tiến trình đích Reduce(mych:channel,op:op_type, res:Result_type, root: int,tag:int, msg:message_type); Trong đó, Op_type = {MAX, MIN, SUM, PROD, LAND, LOR, BAND, BOR, LXOR, BXOR}} - 11 - Ví dụ: hình 3-7 mơ tả hàm Reduce() tập hợp giá trị từ n tiến trình thực phép cộng (SUM) tiến trình gốc Tiến trình Dữ liệu Tiến trình n-1 Tiến trình Dữ liệu Dữ liệu buf Reduce(); + Reduce(); Reduce(); Hình 3-7 Hoạt động hàm Reduce() Trong mơ hình SIMD lệnh Reduce() không thực tất tiến trình thực lời gọi Reduce() Scatter(): phân tán công việc cho tiến trình Dữ liệu mảng buff chia nhỏ thành n đoạn phân tán cho n tiến trình kênh mych Scatter(mych:channel, n:int, Buff[N]:DataType); Hàm sử dụng để gửi phần tử thứ i mảng liệu tới cho tiến trình thứ i Hình 3-8 mơ tả hoạt động Scatter() Tương tự trường hợp Broadcast(), lệnh Scatter() không thực tất tiến trình thực lời gọi Scatter() Tiến trình Dữ liệu Tiến trình n-1 Tiến trình Dữ liệu Dữ liệu buf Scatter(); Scatter(); Scatter(); Hình 4-8 Hoạt động hàm Scatter() Gather(): ngược lại so với hàm Scatter(), liệu gửi theo hàm Scatter() xử lý tiến trình nhận sau tập hợp lại cho tiến trình - 12 - Gather(mych:channel,Buff[N]:DataType,root:int); Ngược lại hàm Scatter(), liệu từ tiến trình thứ i nhận tiến trình gốc đưa vào phần tử thứ i mảng buf, mơ tả hình 3-9 Tiến trình Dữ liệu Tiến trình n-1 Tiến trình Dữ liệu Dữ liệu buf Gather(); Gather(); Gather(); Hình 3-9 Hoạt động hàm Gather() Barrier(): thực việc đồng hố tiến trình gia nhập kênh truyền thơng Mỗi tiến trình phải chờ tất tiến trình khác kênh đạt đến điểm đồng hoá lời gọi Barrier() chương trình Barrier(mych:channel); IV- Lập trình cụm máy tính PVM cung cấp mơi trường phần mềm để gửi/nhận thơng báo cho hệ máy tính khơng PVM có tập hợp hàm thư viện viết C/C++ Fortran Tập máy tính sử dụng mạng phải định nghĩa theo mức ưu tiên để chạy chương trình Điều thực tập máy ảo song song PVM Cách thực tốt tạo danh sách tên gọi máy tính đặt hostfile Tệp PVM đọc để thực chương trình Mỗi máy tính chạy hay nhiều tiến trình (chương trình ứng dụng) Các chương trình ứng dụng chạy máy tính thơng qua tiến trình PVM để trao đổi với mạng hình 310 Các tiến trình PVM u cầu đủ thơng tin để chọn lựa đường truyền thông liệu - 13 - Máy tính trạm `PVM Chương trình ứng dụng Máy tính trạm Máy tính trạm PVM Chương trình ứng dụng Trao đổi thơng điệp mạng PVM Chương trình ứng dụng Hình 3-10 Sự trao đổi thơng điệp máy tính hệ PVM Các chương trình PVM thường tổ chức theo mơ hình chủ-tớ (masterslave), tiến trình chủ thực trước tiên, sau tiến trình tớ tạo tiến trình chủ Hàm phát sinh tiến trình PVM là: pvm_spawn() Một tiến trình muốn tham gia vào hệ PVM phải ghi danh cách gọi hàm pvm_mytid() Các tiến trình muốn huỷ bỏ gọi hàm pvm_exit() Các chương trình trao đổi thơng điệp với thông qua hàm pvm_send() pvm_recv() Tất thủ tục gửi không bị chặn (dị bộ) cịn thủ tục nhận bị chặn (được đồng bộ) không bị chặn Các thao tác việc gửi nhận liệu thực đệm buffer Nếu liệu gửi danh sách mục có kiểu PVM sử dụng pvm_psend() pvm_precv() Hình 3-11 mơ tả hoạt động hai tiến trình trao đổi mảng liệu với Tiến trình send buffer Tiếp tục xử lý pvm_psend(); Tiến trình Chờ thơng điệp pvm_precv(); Hình 3-11 Gọi hàm pvm_psend() pvm_precv() - 14 - Khi liệu gửi phức tạp, gồm nhiều kiểu khác chúng phải đóng gói lại (pack) để gửi đến buffer, sau tiến trình nhận lại mở gói (unpack) để nhận liệu tương ứng Đó hàm: pvm_pkint() pvm_upkint() cho liệu kiểu int pvm_pkfloat() pvm_upkfloat() cho liệu kiểu float pvm_pkstr() pvm_upkstr() cho liệu kiểu string, v.v Lưu ý: thứ tự mở gói để lấy liệu phải theo thứ tự mà chúng đóng gói tiến trình gửi Bộ đệm buffer để gửi liệu mặc định phải khởi tạo tiến trình gửi lệnh pvm_initsend() Tương tự, lệnh khác trao đổi thơng điệp theo nhóm như: pvm_bcast(), pvm_scatter(), pvm_gather(), pvm_reduce(), v.v - 15 - Ví dụ: Xét chương trình gồm chương trình chủ chương trình tớ Chương trình làm nhiệm vụ đơn giản cộng 1000 số sinh ngẫu nhiên (được lưu …/pvm3/src/rand_data.txt) với /* Chương trình – tiến trình chủ */ #include #include #include #define SLAVE “spsum” // tên trình Slave #define PROC 10 // số tiến trình #define N 1000 // độ dài liệu main(){ int mytid, tids[PROC]; int n = N, nproc = PROC; int no, i, who, msgtype; int data[N], resul[PROC],tot=0; char fn[255]; FILE *fn; mytid = pvm_mytid();//Đăng ký vào PVM /* Các tiến trình tớ bắt đầu làm việc Phát sinh 10 tiến trình */ no = pvm_spawn(SLAVE,(char**)0,0,””,nproc,tids); if(no < nproc){ printf(“Gặp khó khăn việc tạo tiến trình tớ\n”); for(i=0; i < no; i++) pvm_kill(tids[i]); pvm_exit(); exit(1); } /* Mở tệp để đọc khởi tạo Data */ strcpy(fn, getenv(“HOME”); strcat(fn,”/pvm3/src/rand_data.txt”); if((fn = fopen(fn, “r”){ printf(“Không mở tệp: %s\n”, fn); exit(1); } for(i=0; i < n; i++) fscanf(fn, “%d”, &data[i]); /* Phát tán liệu cho tiến trình tớ */ pvm_initsend(PvmDataDefault); // khởi tạo buffer msgtype = 0; pvm_pkint(&nproc, 1, 1); pvm_pkint(tids, nproc,1); - 16 - pvm_pkint(&n, 1, 1); pvm_pkint(data, n, 1); pvm_mcast(tids, nproc, msgtag);// Phát tán (1) /* Nhận kết từ tiến trình tớ */ msgtype = 5; for(i=0; i < nproc; i++){/*Nhận kết tính tổng từ tiến trình tớ*/ pvm_recv(-1, msgtype); pvm_upkint(&who, 1, 1); pvm_upkint(&result[who], 1, 1); printf(“%d từ %d\n”, result[who], who]); } /* Tính tổng tổng nhận */ for(i=0; i < nproc; i++) tot += result[i]; printf(“Tổng số là: %d \n\n”, tot); pvm_exit(); return 0; } /* Chương trình slave */ #include #include ”pvm3.h” #define PROC 10 #define N 1000 main(){ int mytid, tids[PROC]; int n, me, i, nproc, x, msgtype, master; int data[N], sum; mytid = pvm_mytid();//Đăng ký vào PVM /* Nhận liệu từ master */ msgtype = 0; pvm_recv(-1, msgtype); /*Nhận liệu từ (1) */ pvm_upkint(&nproc, 1, 1); pvm_upkint(tids, nproc,1); pvm_upkint(&n, 1, 1); pvm_upkint(data, n, 1); /* Xác định tên tid */ for(i=0; i < nproc; i++) if(mytid == tids[i]){me = i; break;} /* Cộng phần liệu tớ tiến trình tớ */ x = n / nproc; low = me * x; - 17 - high = low + x; for(i = low; i < high; i++) sum += data[i];// Tổng /* Gửi kết cho master */ pvm_initsend(PvmDataDefault); pvm_pkint(&me, 1, 1); pvm_pkint(&sum, 1, 1); msgtype = 5; master = pvm_parent(); pvm_send(master, msgtype); pvm_exit(); return (0); } V- Đánh giá chương trình song song Thời gian thực song song Để đánh giá độ phức tạp tính tốn thuật tốn song song, ngồi số bước tính tốn cịn cần đánh giá thời gian truyền thơng tiến trình Trong hệ thống gửi/nhận thông báo, thời gian gửi/nhận thông báo phải xem thời gian thực thuật toán Thời gian thực song song, ký hiệu gồm hai phần tcomp tcomm = tcomp + tcomm Trong đó, tcomp thời gian tính tốn tcomm - thời gian truyền thơng liệu Thời gian tính toán tcomp xác định giống thuật toán Khi có nhiều tiến trình thực đồng thời cần tính thời gian thực tiến trình phức tạp (thực lâu nhất) Thời gian truyền thơng tcomm lại phụ thuộc vào kích cỡ thơng điệp, vào cấu hình kết nối mạng đường truyền cách thức truyền tải thông điệp, v.v Công thức ước lượng thời gian truyền thông xác định sau: tcomm = tstartup + n * tdata Trong đó, + tstartup : Nó bao gồm thời gian để đóng gói thơng điệp nơi gửi thời gian mở gói nơi nhận Để đơn giản giả thiết thời gian số + tdata thời gian cần thiết để gửi từ liệu (một mục liệu) từ nơi gửi tới nơi nhận, giả thiết hàng số n số từ liệu trao đổi hệ thống Ví dụ: Giả sử cần thực cộng n số hai máy tính, máy cộng n/2 số với tất số lưu máy tính thứ Kết máy tính thứ hai tính xong gửi máy tính thứ để cơng hai kết phận với Bài toán phát biểu sau: Máy tính thứ gửi n/2 số cho máy tính thứ hai - 18 - Cả hai máy tính cộng n/2 số cách đồng thời Máy tính thứ hai gửi kết tính máy tính thứ Máy tính thứ cộng hai kết để có kết cuối Thời gian tính tốn (ở bước 4): tcomp = n/2 + Thời gian truyền thông (ở bước 3): tcomm = (tstartup + n/2 * tdata) + (tstartup + tdata) = 2*tstartup + (n/2 + 1) * tdata Độ phức tạp tính tốn O(n) độ phức tạp truyền thông O(n), độ phức tạp nói chung thuật toán O(n) VI- Kết luận Để áp dụng chế xử lý song song, không thiết phải có hệ đa xử lý vật lý UNIX, Win32 hỗ trợ để tạo nhiều tiến trình khác hệ thống chúng sử dụng để mơ lập trình đa xử lý Hệ thống UNIX cung cấp đặc tính tín hiệu điều khiển Semaphore nhớ chia sẻ để tiến trình xử lý song song cần Trong lập trình chia sẻ nhớ dựa vào tiến trình để giải toán đặt Nhiều hệ điều hành hỗ trợ đa luồng, ví dụ Window, OS/2, UNIX Một số ngơn ngữ lập trình, ví dụ C++, Java hỗ trợ lập trình đa luồng Một tiến trình tranh hoạt động chương trình Mỗi tiến trình kết hợp với nhiều luồng Các luồng xem tập tiến trình Các luồng tiến trình chia sẻ với khơng gian địa chương trình, đoạn liệu mơi trường xử lý, đồng thời có vùng liệu riêng để thao tác Một mơ hình lập trình song song sử dụng phổ biến mơ hình gửi/nhận thơng báo Trong mơ hình gửi/nhận thơng báo, tiến trình chia sẻ với kênh truyền thông Kênh truyền thông khái niệm trừu tượng đường truyền thông vật lý tiến trình Các kênh truy cập hai phương thức: send() receive() Để bắt đầu trao đổi với tiến trình phải gửi (send) thông điệp vào kênh truyền thông có tiến trình khác u cầu nhận (receive) thơng điệp Sự trao đổi hồn tất liệu gửi từ địa nguồn tới đích Mơ hình gửi/nhận thơng báo nêu sử dụng hiệu để lập trình song song theo cụ máy tính Một mơi trường cho hệ thống nhiều máy tính, cụm máy tính phát triển sử dụng phổ biến PVM PVM cung cấp môi trường phần mềm để gửi/nhận thơng báo cho hệ máy tính khơng PVM có tập hợp hàm thư viện viết C Fortran - 19 - Bài tập Cho đoạn chương trình printf(“I am here\n”); id = create_process(15); printf(“%d is here\n”, id); Bao nhiêu dòng in “ … is here”, số hiệu tiến trình in có theo trật tự cố định qua lần thực hay khơng? Viết đoạn chương trình để tạo hai tiến trình thực tính 2+4+6+8 song song Viết chương trình chương trình song song để tính phép biến đổi ảnh fractal dựa công thức: Zi+1 = zi3 + (c-1)zi – c Trong đó, z0 = 0, c số phức xác định toạ độ điểm ảnh Viết chương trình song song với độ phức tạp O(log n) để tính giá trị đa thức F = a0x0 + a1x1 + a2x2 + … + an-1xn-1 Viết chương trình song song để tính n! sử dụng hai tiến trình thực đồng thời Mỗi tiến trình tính gần nửa dãy kết tiến trình chủ kết hợp hai kết lại 6.Viết chương trình song song để tìm tất số nguyên tố nhỏ N 7.Viết chương trình song song theo luồng (Thread) để tính xác định giá trị cực đại N phần tử 8.Viết chương trình song song theo luồng mơ hình chia sẻ nhớ để thực nhân hai ma trận cấp n×n 9.Xây dựng hệ xử lý hình ống để tính sin x sin x = x – x/3 + x/5 – x/7 + x/9 + 10.Cho biết kết in đoạn chương trình sau: j = 0; k = 0; forall (i = 1; i