Tải bản đầy đủ (.docx) (29 trang)

ĐÁNH GIÁ HIỆU NĂNG TÍNH TÍCH 2 MA TRẬN DẦY ĐẶC (DENSE) SỬ DỤNG MPI

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (618.49 KB, 29 trang )

TRƯỜNG ĐẠI HỌC CÔNG NGHIỆP HÀ NỘI
KHOA CÔNG NGHỆ THÔNG TIN
======***======

BÁO CÁO BTL THUỘC HỌC PHẦN:
TÍNH TỐN HIỆU NĂNG CAO
ĐÁNH GIÁ HIỆU NĂNG TÍNH TÍCH 2 MA TRẬN DẦY
ĐẶC (DENSE) SỬ DỤNG MPI
Giáo viên hướng dẫn: TS. Hà Mạnh Đào
Nhóm sinh viên thực hiện:
1, Trịnh Thế Khánh

Mã SV: 2021602271

2, Lê Tuấn Anh

Mã SV: 2021601643

3, Nguyễn Mỹ Hạnh

Mã SV: 2021600647

Mã Lớp: 20231IT6069001

Nhóm: 1

Hà nội, Năm 2023


LỜI CẢM ƠN
Trước tiên, chúng em muốn gửi lời tri ân chân thành đến TS. Hà Mạnh


Đào, với lòng biết ơn sâu sắc vì những kiến thức quý báu mà thầy đã truyền
đạt cho chúng em và sự tận tâm trong việc hướng dẫn chúng em hoàn thành
đề tài.
Sự giúp đỡ và sự đồng hành của thầy đã đóng vai trị vơ cùng quan
trọng trong q trình nghiên cứu của chúng em. Chúng em rất mong muốn
nhận được ý kiến đóng góp từ thầy để hồn thiện đề tài của chúng em. Sự
phản hồi và góp ý từ thầy sẽ giúp chúng em nắm bắt được các khía cạnh cần
cải thiện và phát triển thêm ý tưởng mới. Chúng em rất trân trọng mọi đóng
góp và mong được học hỏi thêm từ sự chuyên môn và kinh nghiệm của thầy.
Một lần nữa, chúng em xin chân thành cảm ơn TS. Hà Mạnh Đào vì sự
tận tâm và kiến thức mà thầy đã dành cho chúng em. Sự hướng dẫn của thầy
đã thúc đẩy chúng em tiến bộ và trở thành những người học viên tự tin hơn.
2

Chúng em rất biết ơn và sẽ ln mang trong lịng sự tri ân này.
Nhóm chúng em xin chân thành cảm ơn!

Tính tốn hiệu năng cao


LỜI MỞ ĐẦU
Sự phát triển và mở rộng phạm vi ứng dụng của công nghệ thông tin
luôn gặp phải hai thách thức lớn đó là khơng gian nhớ và tốc độ xử lí của máy
tính. Một số bài tốn do thực tiễn và nghiên cứu lý thuyết đặt ra đòi hỏi phải
xử lý nhanh trên một cơ sở dữ liệu đồ sộ, đặc biệt là trong các lĩnh vực trí tuệ
nhân tạo, nhận dạng, xử lí ảnh, điều khiển tự động, mơ phỏng, các bài tốn dự
báo,... mà các phương pháp và cơng cụ tính tốn truyền thống khơng thể đáp
ứng được. Trong những trường hợp ấy, ta có thể tìm cách phân rã bài tốn
thành những bài tốn có kích thước và quy mơ dữ liệu nhỏ hơn. Tuy nhiên
điều đó khơng phải bao giờ cũng có thể thực hiện. Xử lí song song (parallel

processing) là một trong những giải pháp giúp ta có thể xử lý tình huống nêu
trên. Hiện nay có rất nhiều chuẩn hỗ trợ lập trình song song như MPI hỗ trợ
lập trình song song trên bộ nhớ phân tán, OpenMP hỗ trợ lập trình trên bộ nhớ
chia sẽ chung, Pthread hỗ trợ lập trình luồng,...
3

Bài báo này giới thiệu những kiến thức cơ bản về tính tốn song song
và lập trình song song. Ngồi ra cịn trình bày khái niệm về MPI (Message
Passing Interface), những nguyên tắc lập trình song song với MPI. Sử dụng
thư viện hàm MPI lập trình minh họa bài tốn nhân hai ma trận bằng thuật
toán Cannon. Rút ra những kết luận về thời gian chạy chương trình bằng giải
thuật tuần tự và bằng giải thuật song song.
Do kiến thức, kinh nghiệm cịn hạn chế nên bài báo cáo có thể cịn có
một số lỗi sai, chương trình có thể không đúng trong một vài trường hợp,
mong thầy và các bạn góp ý, giúp đỡ để chúng em hồn thiện hơn.

Tính tốn hiệu năng cao


MỤC LỤC

4

Chương 1. Tổng quan về mơ hình lập trình song song với MPI..........................5
1.1 Tính tốn song song..............................................................................5
1.1.1 Tính tốn song song là gì?..............................................................5
1.1.2 Tại sao phải tính tốn song song?..................................................5
1.1.3 Các thành phần liên quan đến tính tốn song song........................6
1.1.4 Nguyên lý thiết kế thuật toán song song........................................6
1.2 Giới thiệu về MPI.................................................................................8

1.2.1 Khái niệm về MPI..........................................................................8
1.2.2 Mơ hình lập trình truyền thơng điệp (message passing)................8
1.2.3 Các giao thức trong MPI................................................................9
1.2.4 Nguyên tắc lập trình MPI.............................................................10
1.2.5 Các hàm MPI thường dùng..........................................................10
Chương 2. Phương pháp giải quyết bài toán......................................................12
2.1 Bài toán nhân 2 ma trận dày đặc (dense) và thuật toán Cannon.........12
2.1.1 Ma trận dày đặc (dense) là gì?......................................................12
2.1.2 Phép nhân 2 ma trận.....................................................................12
2.1.3 Thiết kế thuật toán song song nhân 2 ma trận dày đặc (dense)....12
2.2 Tính tích 2 ma trận bằng thuật toán tuần tự và thuật toán song song. 16
2.2.1 Thuật toán tuần tự.........................................................................16
2.2.2 Thuật toán song song....................................................................17
2.3 Một số vấn đề về hiệu năng................................................................24
Chương 3. Thực nghiệm và kết quả...................................................................26
3.1 Cấu hình thiết bị..................................................................................26
3.2 Kết quả thực hiện................................................................................27
3.3 Kết luận...............................................................................................28
Tài liệu tham khảo...............................................................................................29

Tính tốn hiệu năng cao


Chương 1. Tổng quan về mơ hình lập trình song
song với MPI
1.1 Tính tốn song song
1.1.1

Tính tốn song song là gì?


Như chúng ta đã thấy các phần mềm phổ biến ngày nay hầu hết đều được
viết trên cơ sở của tính tốn tuần tự. Các phần mềm này thường được thực
hiện trên một máy tính đơn với duy nhất một bộ xử lý. Vấn đề ở đây được
giải quyết thông qua một chuỗi các lệnh tuần tự được thực hiện bởi một bộ xử
lý. Tại một thời điểm chỉ có một lệnh được thực hiện.
Tính tốn song song ra đời là một sự cải tiến của tính tốn tuần tự. Nó là
sự giải quyết vấn đề dựa trên sự thực thi đồng thời của nhiều tài nguyên máy
tính.
Tài nguyên máy tính đây bao gồm:
5

- Một máy tính đơn với nhiều bộ xử lý
- Nhiều máy tính nối lại với nhau thành một mạng máy tính
- Kết hợp cả hai loại trên
Tính tốn song song thường được dùng để giải quyết các vấn đề hết sức
phức tạp yêu cầu thời gian tính tốn lớn hoặc làm việc với khối dữ liệu lớn
như các bài tốn dự báo thời tiết, mơ phỏng tai nạn xe hơi, xây dựng các mơ
hình thương mại và các vấn đề khoa học như khai phá dữ liệu , trí tuệ nhân
tạo, an tồn dữ liệu…
1.1.2

Tại sao phải tính tốn song

song?
Việc tính tốn song song là rất cần thiết. Ngồi hai ngun nhân chính là
nó được dùng để tính tốn các bài tốn u cầu thời gian tính tốn lớn và
khối lượng dữ liệu lớn cịn có các nguyên nhân khác như để sử dụng tài
nguyên của các máy khác trong một mạng LAN hoặc thông qua mạng
internet, có thể sử dụng nhiều tài ngun tính tốn nhỏ kết hợp lại tạo nên một
siêu máy tính. Do giới hạn về không gian lưu trữ của bộ nhớ trên một máy

Tính tốn hiệu năng cao


đơn để giải quyết một vấn đề lớn việc sử dụng nhiều bộ nhớ trên nhiều máy
tính là rất hữu hiệu trong trường hợp này.
Giới hạn của tính tốn tuần tự bao gồm cả hai nguyên nhân thực tế và
nguyên nhân vật lý. Để xây dựng nên một máy tính tuần tự tốc độ cao gặp rất
nhiều hạn chế:
- Về tốc độ truyền dữ liệu: Tốc độ truyền của máy tính tuần tự phụ thuộc
trực tiếp vào sự di chuyển dữ liệu trong phần cứng. Cho nên việc tăng
tốc độ thực hiện phải chủ yếu căn cứ vào các yếu tố tính tốn.
- Về kích cỡ: Cơng nghệ chế tạo bộ xử lý cho phép gắn nhiều bóng bán
dẫn trên một con chip. Tuy nhiên việc làm này sẽ làm tăng kích thước
của bộ xử lý
- Về thương mại: Việc tạo ra một bộ xử lý tốc độ xử lý cao là rất tốn
kém.
Sử dụng nhiều bộ xử lý nhỏ đạt hiệu quả tương tự mà lại ít tốn kém hơn.
1.1.3

6

Các thành phần liên quan đến

tính tốn song song
- Kiến trúc máy tính song song.
- Phần mềm hệ thống.
- Giải thuật song song.
- Ngơn ngữ lập trình song song.
1.1.4


Ngun lý thiết kế thuật toán

song song
Khi muốn thực hiện việc xử lí song song ta phải xét cả kiến trúc máy tính
và các thuật tốn song song. Để thiết kế được các thuật toán song song cần
phải thực hiện:
- Phân chia dữ liệu cho các tác vụ.
- Chỉ ra cách truy cập và chia sẻ dữ liệu.
- Phân các tác vụ cho các tiến trình (bộ xử lí).
- Các tiến trình được đồng bộ ra sao
Tính tốn hiệu năng cao


Khi thiết kế một thuật tốn song song có thể sử dụng năm ngun lí
chính trong thiết kế thuật tốn song song:
- Nguyên lý lập lịch: mục đích là giảm tối thiểu các bộ xử lí sử dụng
trong thuật tốn sao cho thời gian tính tốn là khơng tăng (xét theo khía
cạnh độ phức tạp).
- Ngun lý hình ống: Ngun lý này được áp dụng khi bài toán xuất
hiện một dãy các thao tác {T1, T2, . . ., Tn}, trong đó Ti+1 thực hiện
sau khi Ti kết thúc.
- Nguyên lý chia để trị: Chia bài toán thành những phần nhỏ hơn tương
đối độc lập với nhau và giải quyết chúng một cách song song.
- Nguyên lý đồ thị phụ thuộc dữ liệu: Phân tích mối quan hệ dữ liệu
trong tính tốn để xây dựng đồ thị phụ thuộc dữ liệu và dựa vào đó để
xây dựng thuật tốn song song.
- Nguyên lý điều kiện tương tranh: Nếu hai tiến trình cùng muốn truy
7

cập vào cùng một mục dữ liệu chia sẻ thì chúng phải tương tranh với

nhau, nghĩa là chúng có thể cản trở lẫn nhau.
Ngồi những ngun lý nêu trên, khi thiết kế thuật tốn song song ta
cịn phải chú ý đến kiến trúc của hệ thống tính toán. Khi chuyển một thuật
toán tuần tự sang thuật toán song song hoặc chuyển một thuật tốn song song
thích hợp với kiến trúc đang có. Cần xác định được yêu cầu sau:
- Kiến trúc tính tốn nào sẽ phù hợp với bài toán?
- Những bài toán loại nào sẽ xử lý hiệu quả trong kiến trúc song song
cho trước ?

Tính toán hiệu năng cao


1.2 Giới thiệu về MPI
1.2.1

Khái niệm về MPI

Là viết tắt của Message Passing Interface, chỉ một dạng giao thức kết nối
của máy tính. Nó nằm trong chuẩn “de facto” cho kết nối giữa các nút chạy
một chương trình song song trên bộ nhớ phân tán. Tập MPI thi hành bao gồm
một thư viện các thủ tục sao cho có thể gọi được từ các chương trình Fortran,
C, C++ hay Ada.
MPI ra đời mục đích dành cho các hệ thống máy tính có bộ nhớ phân tán.
Tuy nhiên MPI cũng có thể triển khai được trên hệ thống máy tính có bộ nhớ
chia sẻ.
Lợi thế của MPI so với các thư viện cũ là nó vừa thuận tiện (vì MPI thực
thi cho hầu hết các kiến trúc bộ nhớ phân phối) vừa nhanh (vì mỗi thủ tục
được tối ưu hóa cho phần cứng mà nó đang chạy). Thường được so sánh với
PVM (Parallel Virtual Machine) và có thể kết hợp nó để tạo thành
8


PVM_MPI.
1.2.2

Mơ hình lập trình truyền

thơng điệp (message passing)
Trong khoa học máy tính, truyền thơng điệp (tiếng Anh: message passing)
là kỹ thuật để gọi hành vi (ví dụ như chạy chương trình) trên máy tính.
Chương trình gọi sẽ gửi thơng điệp tới một q trình (có thể là tác nhân hay
đối tượng) và dựa vào quy trình với cơ sở hạ tầng hỗ trợ để chọn và gọi mã
thực sự để chạy. Truyền thơng điệp khác với lập trình thơng thường ở chỗ q
trình, chương trình con, hay hàm được gọi trực tiếp bằng tên. Truyền thơng
điệp là chìa khóa cho một số mơ hình lập trình tương tranh và hướng đối
tượng.
Truyền thông điệp được sử dụng phổ biến trong phần mềm máy tính hiện
đại. Nó được sử dụng như một cách để các đối tượng tạo nên một chương
trình hoạt động với nhau và là phương tiện để các đối tượng và hệ thống chạy

Tính tốn hiệu năng cao


trên các máy tính khác nhau (ví dụ trên Internet) tương tác. Truyền thơng điệp
có thể dược hiện thực theo nhiều cơ chế khác nhau, bao gồm các kênh.
Mơ hình lập trình truyền thơng điệp được phát triển dựa trên ý tưởng lập
trình song song. Trong đó bài tốn được chia thành nhiều node(phần) nhỏ,
mỗi node được giải quyết trên một processor với bộ nhớ riêng. Các nodes này
sẽ giao tiếp với nhau qua một hoặc nhiều mạng cục bộ thông qua các message
để cùng nhau giải quyết vấn đề của bài tốn. Các nodes truyền thơng tin cho
nhau thơng qua các link (kết nối) và được gọi là external channels (kênh

ngồi).

9

Hình 1: Mơ hình truyền thơng điệp
Ví dụ: tính y=(a+b)×(c+d)
Tính trên 1 processor phải thơng qua 8 bước. Nhưng tính trên 2 processor
chỉ cần thơng qua 7 bước.
Bước
tính
1
2
3
4
5
6
7
8

Cơng việc
Đọc a, b
Tính a+b
Lưu kết quả
Đọc c, d
Tính c+d
Tính (a+b)*(c+d)
Ghi kết quả
Kết thúc

Bước

tính
1
2
3
4
5
6
7

Cơng việc trên
Processor 1
Đọc a, b
Tính a+b
Gửi kết quả cho P2
Kết thúc

Cơng việc trên
Processor 2
Đọc c, d
Tính c+d
Lưu kết quả
Nhận kết quả từ P1
Tính (a+b)*(c+d)
Ghi kết quả
Kết thúc

Tính tốn hiệu năng cao


1.2.3


Các giao thức trong MPI

Giao thức Point to Point: là giao thức đơn giản nhất trong truyền thông
điệp. Một thông điệp được truyền từ một processor này tới một processor
khác và chỉ hai processor này mới biết được thông tin trong thơng điệp đó.
Khi một Processor thực hiện giao thức truyền tin (send) thì một Prosessor
khác phải có giao thức nhận tin (receive) tương ứng.
Giao thức Collective: là giao thức cho phép nhiều processor trao đổi
thông điệp cùng nhau.
1.2.4

Nguyên tắc lập trình MPI

Tất cả chương trình sử dụng MPI phải bắt đầu với hàm MPI_Init() và kết
thúc với hàm MPI_Finalize() và MPI_Init chỉ được gọi một lần duy nhất
trong toàn bộ chương trình.
1.2.5

10

Các hàm MPI thường dùng

Tên hàm

Ý nghĩa

MPI_Init()

Khởi tạo bộ môi trường thực thi MPI, hàm này

phải được gọi trước tất cả các hàm MPI khác, và
chỉ được gọi một lần.

MPI_Finalize()

Dùng để kết thúc môi trường thực thi MPI. Hàm
này phải được gọi cuối cùng trong tất cả các hàm
MPI

MPI_Comm_size( MPI Xác định số lượng tiến trình tham gia vào một bộ
_COMM_WORLD,
giao tiếp, thơng thường, nó được dùng trong bộ
&size)
giao tiếp MPI_COMM_WORLD bộ giao tiếp
được xây dựng sẵn, bao gồm tất cả các tiến trình
tham gia vào chương trình
MPI_Comm_rank( MPI Xác định thứ tự của tiến trình này trong bộ giao
_COMM_WORLD,
tiếp. Lúc ban đầu mỗi tiến trình được gán cho
&rank)
một số thứ tự từ 0 tới n-1 trong bộ giao tiếp

Tính tốn hiệu năng cao


MPI_COMM_WORLD
MPI_Finalized(&flag)

Kiểm tra xem hàm MPI_Init() đã được gọi hay
chưa


MPI_Barrier()

Đồng bộ tất cả các tiến trình trong hệ thống, khi
hàm này được gọi, tất cả các tiến trình sẽ cùng
chờ cho tới khi tiến trình cuối cùng thực hiện đến
bước này và tất cả cùng thực hiện câu lệnh tiếp
theo vào cùng một thời điểm

MPI_Wtime()

Xác định thời gian của hệ thống

MPI_Status

Biểu thị trạng thái của hoạt động tiếp nhận, được
trả về bởi hoạt động nhận (MPI_Recv), chờ hoạt
động không chặn (MPI_Wait, MPI_Waitall,
MPI_Waitany và MPI_Waitsome) hoặc kiểm tra
(MPI_Test, MPI_Testall, MPI_Testany và
MPI_Testsome).

MPI_Request

Đại diện cho một xử lý trên một hoạt động không
chặn(a non-blocking operation)

MPI_Irecv()

MPI Receive with Immediate return(Nhận và trả

lại ngay lập tức) Bắt đầu thao tác nhận và trả về
một xử lý cho thao tác giao tiếp được yêu cầu.

MPI_Isend()

Bắt đầu thao tác gửi ở chế độ tiêu chuẩn và trả về
một điều khiển cho thao tác giao tiếp được yêu
cầu.

MPI_Wait()

Một lệnh gọi MPI_Wait trả về khi thao tác được
xác định theo u cầu hồn tất.

11

MPI_Reduce(void
Hàm tính gộp, dùng để gộp các kết quả của từng
*local, void *global, int tiến trình vào kết quả chung. Trong đó, local là
Tính tốn hiệu năng cao


count, MPI_Datatype
type, MPI_Op operator,
int root, MPI_Comm
comm)

kết quả cục bộ, global là kết quả nhận được sau
khi tính gộp các kết quả cục bộ, type là kiểu dữ
liệu tính gộp, operator là thao tác tính gộp, root là

thứ tự của tiến trình sẽ nhận được kết quả global,
comm là bộ giao tiếp

12

Tính tốn hiệu năng cao


Chương 2.

Phương pháp giải quyết bài toán

2.1 Bài toán nhân 2 ma trận dày đặc (dense) và thuật toán Cannon
2.1.1

Ma trận dày đặc (dense) là gì?

Trong phân tích số và tính tốn khoa học, ma trận dày đặc hoặc mảng dày
đặc là ma trận mà trong đó hầu hết các phần tử đều khác 0 (có rất ít số 0, số
phần tử bằng 0 thường gần bằng số hàng hoặc số cột). Ngược lại, nếu hầu hết
các phần tử bằng 0, ma trận đó được coi là ma trận thưa (Sparse).
2.1.2

Phép nhân 2 ma trận

Trong toán học, phép nhân ma trận là phép toán nhị phân tạo ra ma trận từ
hai ma trận. Để nhân ma trận, số lượng cột trong ma trận thứ nhất phải bằng
số lượng hàng trong ma trận thứ hai. Ma trận kết quả, được gọi là tích ma
trận, có số lượng hàng của ma trận đầu tiên và số cột của ma trận thứ hai.
Nếu A là ma trận m×n và B là ma trận n×p, thì tích ma trận C = B (ký

hiệu khơng có dấu nhân hoặc dấu chấm) được xác định là ma trận m×p.
13

Với cơng thức:
2.1.3 Thiết kế thuật tốn song song nhân 2 ma trận dày đặc (dense)
Để đơn giản, chúng ta sẽ làm việc với ma trận vng kích thước n ×n. Coi
số lượng bộ xử lý có sẵn trong các máy song song là p. Ma trận cần nhân sẽ là
Tính tốn hiệu năng cao


2 ma trận dày đặc (có ít số 0) A và B có cùng kích thước n ×n. Kết quả sẽ
được lưu trữ trong ma trận C.
Ta thực hiện phép nhân theo các bước sau:
B1: Chia ma trận thành các khối vng Pi, trong đó Pi là các threads có sẵn
(vd 4 threads thì có P0, P1, P2, P3).
B2: Tạo ma trận các quy trình có kích thước P*1/2 × P*1/2 sao cho mỗi q
trình có thể duy trì một khối ma trận A con và một khối ma trận B con.
B3: Mỗi khối được gửi đến từng quy trình và phần phụ được sao chép từ các
khối được nhân với nhau và kết quả được thêm vào trong các tiểu khối C.
B4: Các khối con A được đẩy sang trái một bước và các khối con B được
cuộn lên một bước.
B5: Lặp lại bước 3 & 4 √ p lần.
Ví dụ:
Cho 2 ma trận dày đặc A và B có kích thước 4x4
14

Hình 2: ví dụ ma trận dày đặc
Cho p=4, chia ma trận A và ma trận B thành 4 khối:

Tính tốn hiệu năng cao



Hình 3: Tách ma trận thành các khối 1
Căn chỉnh ma trận:

15

Hình 4: Căn chỉnh ma trận
Mỗi khối được gửi đến từng quy trình và phần phụ được sao chép từ các
khối được nhân với nhau và kết quả được thêm vào trong các tiểu khối C.

Tính tốn hiệu năng cao


Hình 5: Nhân các ma trận con
Các khối con A được đẩy sang trái một bước và các khối con B được
cuộn lên một bước.

16

Hình 6: Đổi vị trí
Lặp lại bước 3 & 4 √p lần:

Tính tốn hiệu năng cao


Hình 7: Lặp lại bước 3&4

17


2.2

Tính tích 2 ma trận bằng thuật toán tuần tự và thuật toán song
song.

2.2.1 Thuật tốn tuần tự
// Thuật tốn song song Cannon tính tích 2 ma trận dày đặc (Dense)
#include <bits/stdc++.h>
#include <time.h>
using namespace std;
#define N 500
clock_t tstart, tend;
int main()
{
static int a[N][N];
static int b[N][N];
static int c[N][N];
for (int i = 0; i < N; i++) { //let's make fist matrix
for (int j = 0; j < N; j++) {
Tính tốn hiệu năng cao


a[i][j] = (int)rand() % 100 + 1;
b[i][j] = (int)rand() % 100 + 1;
c[i][j] = 0;
}
}
tstart = clock();
int i, j, k;
for (i = 0; i < N; i++) {

for (j = 0; j < N; j++) {
int tt = 0;
for (k = 0; k < N; k++)
{
tt = tt + (a[i][k] * b[k][j]);
}
c[i][j] = tt;
}
}
/*for(i=0;ifor(j=0;jcout<}
cout<}*/
tend = clock();
double time_use = (double)(tend - tstart) / CLOCKS_PER_SEC;
cout << "Time is " << setprecision(10) << time_use << endl;
return 0;

18

}
Độ phức tạp: Đây là phép nhân giữa 2 ma trận vng cấp n, vì vậy, số
lượng phép toán cơ bản giữa các đại lượng vơ hướng là 2n³-n² = O(n³).
2.2.2 Thuật tốn song song
// Thuật tốn song song Cannon tính tích 2 ma trận dày đặc (Dense)
#include <mpi.h>
#include <stdio.h>
#include <math.h>

#include <iostream>
using namespace std;
int x = 0;
double kk;
int proces;
int numprocs;
Tính tốn hiệu năng cao


19

int right_neigh, left_neigh, up_neigh, down_neigh;
int tag = 99;
static const int n = 1000; //size of matrices
const int PP = 2; // square root of the number of processes
static int a[n][n];
static int b[n][n];
static int c[n][n];
static int outa[n][n];
static int outb[n][n];
static int outc[n][n];
double startTime, endTime;
int main(int argc, char** argv)
{
for (int i = 0; i < n; i++) { //let's make fist matrix
for (int j = 0; j < n; j++) {
a[i][j] = (int)rand() % 100 + 1;
b[i][j] = (int)rand() % 100 + 1;
c[i][j] = 0;
}

}
for (int i = 0; i < n; i++) { //let's make fist matrix
for (int j = 0; j < n; j++) {
outa[i][j] = a[i][j];
outb[i][j] = b[i][j];
}
}
MPI_Status statRecv2;
MPI_Request reqSend2, reqRecv2;
MPI_Status statRecv[2];
MPI_Request reqSend[2], reqRecv[2];
MPI_Init(&argc, &argv);
MPI_Comm_rank(MPI_COMM_WORLD, &proces);
MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
int pra[n / PP][n / PP] = {}, psa[n / PP][n / PP] = {};// submatrices
int prb[n / PP][n / PP] = {}, psb[n / PP][n / PP] = {};
double np = numprocs;
kk = sqrt(np);
int k = (int)kk;
// split the main matrix into submatrices, each process gets a
different submatrix
for (int i = 0; i < n / PP; i++)
{
for (int j = 0; j < n / PP; j++)
{
Tính tốn hiệu năng cao


psa[i][j] = a[proces/PP*(n/PP) + i][proces%PP*(n/PP) + j];
psb[i][j] = b[proces/PP*(n/PP) + i][proces%PP*(n / PP) + j];

//cout << A[proces/PP*(n/PP) + i][proces%PP*(n/PP) + j] << "
";
}
//cout << endl;

20

}
if (proces < k) // below neighbour set
{
left_neigh = (proces + k - 1) % k;
right_neigh = (proces + k + 1) % k;
up_neigh = ((k - 1) * k) + proces;
}
if (proces == k)
{
left_neigh = ((proces + k - 1) % k) + k;
right_neigh = ((proces + k + 1) % k) + k;
up_neigh = proces - k;
}
if (proces > k)
{
x = proces / k;
left_neigh = ((proces + k - 1) % k) + x * k;
right_neigh = ((proces + k + 1) % k) + x * k;
up_neigh = proces - k;
}
if (proces == 0 || (proces / k) < (k - 1))
{
down_neigh = proces + k;

}
if ((proces / k) == (k - 1))
{
down_neigh = proces - ((k - 1) * k);
}
x = 0;
int p = 0;
startTime = MPI_Wtime();
do { // offsets
if (p < proces / PP)// in line
{
MPI_Irecv(pra, n*n/PP/PP, MPI_FLOAT, right_neigh,
tag, MPI_COMM_WORLD, &reqRecv2);
MPI_Isend(psa, n*n/PP/PP, MPI_FLOAT, left_neigh,
tag, MPI_COMM_WORLD, &reqSend2);
Tính tốn hiệu năng cao



×