Trong suốt bốn thập kỷ gần đây, tiến bộ của công nghệ máy tính đã mở ra những khả năng mới đầy hứa hẹn. Sự gia tăng về hiệu suất của vi xử lý, theo xu hướng tăng theo thời gian, đã tạo ra bước tiến quan trọng, đánh dấu sự xuất hiện của nhiều đổi mới công nghệ. Các lĩnh vực như trí tuệ nhân tạo, internet vạn vật và nhiều lĩnh vực khác đã mở rộng và phát triển nhờ vào sự nâng cao này. Tuy nhiên, như mọi thứ khác, sự phát triển này cũng đối mặt với những thách thức. Giới hạn về vật lý và sự hạn chế trong việc tăng cường hiệu suất phần cứng đặt ra một câu hỏi quan trọng: Làm thế nào chúng ta có thể tiếp tục cải thiện khả năng tính toán? Trong bối cảnh này, tính toán song song trở thành một hướng đi quan trọng. Thay vì chỉ tập trung vào việc cải thiện tốc độ của phần cứng, chúng ta đang nghiên cứu cách thức tính toán có thể được tối ưu hóa. Tính toán song song, một chiến lược đã tồn tại từ lâu, là một trong những phương pháp quan trọng nhất trong lĩnh vực này. Trong nghiên cứu này, chúng em sẽ mô phỏng sức mạnh của tính toán song song thông qua việc giải quyết bài toán nhân ma trận trên cả hai mô hình và đưa ra so sánh về hiệu suất. Mặc dù đã nỗ lực hết sức để tránh những sai sót, nhưng chúng em nhận thức rằng có thể vẫn tồn tại những khuyết điểm nhỏ và mong nhận được sự thông cảm.
CƠ SỞ TÍNH TOÁN SONG SONG
Khái niệm
Tính toán song song là phương pháp cho phép thực hiện nhiều tác vụ tính toán đồng thời, thay vì theo trình tự Phương pháp này tận dụng các tài nguyên tính toán độc lập như bộ xử lý đa lõi, máy tính đa nòng hoặc mạng máy tính phân tán để gia tăng hiệu suất và tốc độ xử lý.
So sánh tính toán song song và tính toán tuần tự:
Tính toán song song (parallel computing)
Được chạy trên máy tính đơn với một bộ xử lý trung tâm
Mộ bài toán (problem) sẽ được chia thành một chuỗi các câu lệnh rời rạc
Các câu lệnh được thực hiện một cách tuần tự
Tại mỗi thời điểm chỉ thực hiện được một câu lệnh.
Để chạy trên nhiều CPU.
Một bài toán được chia thành các phần riêng biệt mà có thể được giải quyết đồng thời
Mỗi phần được chia nhỏ hơn dưới một dãy các câu lệnh
Các câu lệnh của mỗi phần thực thi đồng thời trên các CPU khác nhau.
Tài nguyên
Các nguồn tài nguyên tính toán có thể bao gồm:
- Một máy tính đơn với nhiều bộ vi xử lý (CPU).
- Một máy tính đơn với một hoặc nhiều CPU và một số tài nguyên chuyên dụng như GPU, FPGA …
- Một số lượng tuỳ ý các máy tính được kết nối bởi một mạng máy tính
- Hoặc kết hợp của cả hai loại trên.
Vấn đề tính toán
Vấn đề tính toán thường được thể hiện qua các đặc điểm như khả năng:
- Chia thành các phần riêng biệt các công việc để có thể giải quyết cùng một lúc.
- Thực thi nhiều câu lệnh chương trình tại nhiều thời điểm.
- Giải quyết bài toán trong thời gian ít hơn với nhiều tài nguyên tính toán hơn là thực thi chỉ trên một tài nguyên tính toán duy nhất.
Ứng dụng
Tính toán song song đại diện cho sự tiến hóa của tính toán tuần tự, nhằm mô phỏng các trạng thái phức tạp trong thế giới tự nhiên Trong môi trường này, nhiều sự kiện liên quan diễn ra đồng thời, nhưng vẫn nằm trong cùng một chuỗi, phản ánh tính chất đa dạng và phong phú của thực tại.
+ Quỹ đạo hành tinh và thiên hà
+ Các mô hình thời tiết và đại dương
+ Các hoạt động hàng ngày trong một doanh nghiệp
Tính toán song song, được xem là “tính toán hiệu năng cao”, đóng vai trò quan trọng trong việc mô phỏng các hệ thống phức tạp và giải quyết những bài toán lớn.
+ Dự báo thời tiết và khí hậu
+ Các phản ứng hoá học và hạt nhân
+ Các bài toán sinh học và gen người
+ Các hoạt động địa chất
+ Các thiết bị cơ khí – như chân tay giả cho tàu vũ trụ
+ Các quy trình sản xuất
Ngày nay, ứng dụng thương mại đóng vai trò quan trọng trong việc thúc đẩy các nhà phát triển máy tính và phần mềm tạo ra các hệ thống có tốc độ xử lý nhanh hơn Điều này là do các ứng dụng này cần xử lý một khối lượng dữ liệu lớn và có độ phức tạp cao.
Ví dụ như các ứng dụng:
+ Các cơ sở dữ liệu song song, data mining
+ Các máy chủ tìm kiếm, các dịch vụ thương mại
+ Máy tính trợ giúp chuẩn đoán trong y học
+ Quản lý các tập đoàn quốc gia và đa quốc gia
+ Cải tiến đồ hoạ và ảo hoá
+ Video mạng và các công nghệ đa phương tiện
+ Môi trường làm việc cộng tác
Lợi ích
- Giải quyết những bài toán lớn
- Xử lý đồng thời cùng một lúc
Tận dụng tài nguyên tính toán từ mạng diện rộng là một giải pháp hiệu quả khi các tài nguyên cục bộ hạn chế Sử dụng Internet để khai thác các nguồn tài nguyên này giúp tối ưu hóa hiệu suất và đáp ứng nhu cầu công việc một cách linh hoạt.
- Tiết kiệm chi phí – sử dụng nhiều tài nguyên máy tính “rẻ” thay vì phải đầu tư một con siêu máy tính
Để khắc phục hạn chế về bộ nhớ, các máy tính đơn thường có tài nguyên bộ nhớ rất hạn chế Đối với những bài toán lớn, việc sử dụng bộ nhớ của nhiều máy tính có thể giúp vượt qua những trở ngại này.
TỔNG QUAN VỀ MPI
Khái niệm
Message Passing Interface (MPI) là một giao thức kết nối giữa các máy tính, đóng vai trò quan trọng trong việc thực hiện các chương trình song song trên hệ thống bộ nhớ phân tán MPI được công nhận là chuẩn “de facto” cho việc giao tiếp giữa các nút trong môi trường tính toán 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.
Lập trình MPI
MPI được phát triển nhằm phục vụ cho các hệ thống máy tính với bộ nhớ phân tán Bên cạnh đó, MPI cũng có khả năng triển khai trên các hệ thống máy tính sử dụng bộ nhớ chia sẻ.
Yêu cầu cho mọi chương trình được lập trình bởi MPI Định dạng các hàm trong MPI
Hình 2.2 Minh họa Header file
Cấu trúc của chương trình MPI
Hình 2.3 Cấu trúc chương trình MPI
Truyền thông và nhóm (Communicators and Groups)
Communicators và Group là tập hợp các processes có khả năng giao tiếp với nhau, trong đó hầu hết các hàm trong thư viện MPI yêu cầu tham số Communicator MPI_COMM_WORLD là một communicator đã được định nghĩa sẵn.
Hình 2.4 Truyền thông và nhóm
Rank
Với mỗi Communicator, mỗi processes có một ID nhất định.
Rank được bắt đầu từ 0
Sử dụng rank trong các message để chỉ ra nguồn (source) và đích (destination)
Các hàm quản lý môi trường
MPI_Init là hàm khởi tạo môi trường thực thi cho các chương trình MPI Hàm này phải được gọi trước bất kỳ hàm MPI nào khác và chỉ được thực hiện một lần duy nhất trong suốt quá trình chạy chương trình Cú pháp của hàm là int MPI_Init(int *argc, char **argv).
- MPI_Comm_size: Xác định số lượng process trong nhóm ứng với một Communicator (thường là MPI_COMM_WORLD)
- MPI_Comm_rank: Trả về id của Communicator hiện tại int MPI_Comm_size(MPI_Comm comm,int *size ) int MPI_Comm_rank (comm,&rank)
- MPI_Abort: Hủy bỏ tất cả các MPI processes gắn với một Communicator int MPI_Abort(MPI_Comm comm,int errorcode)
- MPI_Finalize: Kết thúc môi trường thực thi MPI int MPI_Finalize()
Các hàm MPI thông dụng
MPI_Ssend MPI_Iallgather MPI_Isend MPI_Iallreduce MPI_Issend MPI_Barrier MPI_Irecv MPI_Ibarrier
MPI_Group_rank MPI_Ibcast
MPI_Group_size MPI_Igather MPI_File_open MPI_Igatherv MPI_File_read MPI_Ireduce MPI_File_read_at MPI_Iscatter MPI_File_write MPI_Iscatterv
BÀI TOÁN NHÂN MA TRẬN
Ma trận
Ma trận là một cấu trúc hình chữ nhật chứa các số, ký hiệu hoặc biểu thức, được sắp xếp theo hàng và cột theo những quy tắc nhất định Mỗi ô trong ma trận được gọi là phần tử, và các phần tử này được xác định bởi hai chỉ số hàng i và cột j, ký hiệu là aij.
Ma trận thường được viết trong dấu ngoặc vuông:
Phép nhân hai ma trận chỉ khả thi khi số cột của ma trận thứ nhất bằng số hàng của ma trận thứ hai Ma trận kết quả, hay còn gọi là tích ma trận, sẽ có số hàng tương ứng với ma trận đầu tiên và số cột tương ứng với ma trận thứ hai.
Nếu ma trận A có kích thước (m x n) và ma trận B có kích thước (n x p), thì ma trận tích C = A x B sẽ có kích thước (m x p) Phần tử tại hàng thứ i và cột thứ j của ma trận C được xác định theo công thức cụ thể.
Minh họa tích ma trận AB của hai ma trận A và B:
Hình 3.2 Minh họa tích ma trận
Ví dụ: cho 2 ma trận:
Hình 3.2 Ví dụ ma trận
Phần tử C12 của ma trận tích AB là tích của vector hàng thứ nhất của A và vector cột thứ hai của B, ta có:
Tính tương tự với tất cả phần tử còn lại của ma trận C Ta được ma trận tích AB có dạng:
Mô tả quá trình nhân ma trận: a Mạng Nơ-ron (Neural Networks):
Mạng nơ-ron sử dụng tích ma trận để thực hiện lan truyền ngược, điều chỉnh trọng số giữa các nơ-ron Trọng số trong mỗi lớp được biểu diễn bằng ma trận, với phép nhân ma trận tính toán đầu ra của từng nơ-ron.
Trong xử lý ảnh, nhân ma trận đóng vai trò quan trọng trong việc thực hiện các phép biến đổi đồ họa Chẳng hạn, khi áp dụng bộ lọc lên hình ảnh, phép nhân ma trận được sử dụng để tính toán giá trị mới cho từng pixel, từ đó cải thiện chất lượng hình ảnh.
Trong đồ họa máy tính, tích ma trận là công cụ quan trọng để thực hiện các phép biến đổi như dịch chuyển, xoay, co giãn và chiếu Bằng cách kết hợp các ma trận biến đổi, người ta có thể tạo ra những hiệu ứng đồ họa phức tạp và sinh động.
Trong các lĩnh vực tính toán khoa học, tích ma trận đóng vai trò quan trọng trong việc giải quyết hệ phương trình tuyến tính, mô phỏng và phân tích dữ liệu số Một ứng dụng nổi bật là trong công nghệ môi trường, nơi tích ma trận được sử dụng để xây dựng các mô hình môi trường hiệu quả.
Trong mô phỏng môi trường và hệ thống sinh thái, nhân ma trận đóng vai trò quan trọng trong việc thể hiện mối quan hệ phức tạp giữa các yếu tố như thời tiết, địa hình và tác động của con người.
Thuật toán nhân ma trận tuần tự
Thuật toán nhân ma trận theo tuần tự sử dụng ba vòng lặp để tính toán từng phần tử của ma trận kết quả.
Vòng lặp ngoài (i) duyệt qua từng hàng của ma trận kết quả.
Vòng lặp giữa (j) duyệt qua từng cột của ma trận kết quả.
Vòng lặp bên trong (k) duyệt qua từng phần tử của hàng i của ma trận A và cột j của ma trận B để tính tổng.
Biến và Kích Thước Ma Trận:
Biến m, n, và p lần lượt là số hàng của ma trận A, số cột của ma trận A (cũng là số hàng của ma trận B), và số cột của ma trận B.
Tạo ma trận kết quả result với kích thước m x p và giá trị ban đầu là 0.
Vòng lặp ngoài (i) duyệt qua từng hàng của ma trận kết quả.
Vòng lặp giữa (j) duyệt qua từng cột của ma trận kết quả.
Vòng lặp bên trong (k) duyệt qua từng phần tử của hàng i của ma trận A và cột j của ma trận B.
Tại mỗi bước, giá trị result[i][j] được cập nhật bằng cộng dồn của tích phần tử A[i][k] và B[k][j].
Ma trận result sau cùng chứa giá trị của tích ma trận A và B.
Một hàm in ra console được sử dụng để hiển thị ma trận kết quả
Code nhân ma trận tuần tự (c++):
Độ phức tạp của thuật toán nhân ma trận tuần tự được đánh giá dựa trên số lần thực hiện các phép toán cơ bản như so sánh, gán giá trị, nhân và cộng Để hiểu rõ hơn về độ phức tạp, chúng ta cần xem xét các thành phần chính của thuật toán này.
Số Lần Thực Hiện Phép Nhân:
Trong một vòng lặp đầy đủ, ta có ba phép nhân: result[i][j] += A[i][k] * B[k][j]. Vòng lặp ngoài (i) chạy m lần.
Vòng lặp giữa (j) chạy p lần.
Vòng lặp bên trong (k) chạy n lần.
Tổng số lần thực hiện phép nhân là m * p * n.
Tổng Số Phép Toán Cơ Bản:
Số phép toán cơ bản bao gồm cả phép nhân và phép cộng trong vòng lặp bên trong.
Trong mỗi vòng lặp bên trong, có một phép cộng và một phép nhân.
Tổng số phép toán cơ bản trong thuật toán là 2 * m * p * n, với độ phức tạp thời gian là O(m * p * n), cho thấy thời gian chạy của thuật toán tăng theo kích thước của ma trận.
Thuật toán này có độ phức tạp không gian O(1), không sử dụng bộ nhớ phụ đặc biệt và không phụ thuộc vào kích thước của ma trận Ưu điểm của nó là sự đơn giản và dễ hiểu, phù hợp cho các ma trận có kích thước nhỏ đến trung bình.
Hạn chế: Độ phức tạp tăng nhanh khi kích thước ma trận lớn.
Thuật toán Canon
Thuật toán Canon MPI là một giải pháp song song trong tính toán phân tán, cho phép thực hiện các phép tính trên cụm máy tính với nhiều nút xử lý Thuật toán này phân chia tác vụ lớn thành các phần nhỏ hơn, từ đó tối ưu hóa quá trình tính toán song song.
Thuật toán nhân ma trận Cannon:
1 Xác định tổng số nút xử lý trong cụm tính toán (p).
2 Tạo một lưới sqrt(p) x sqrt(p) các nút xử lý (được sắp xếp thành các hàng và cột).
3 Chia dữ liệu cần tính toán thành sqrt(p) cột và sqrt(p) hàng.
4 Trong pha di chuyển dữ liệu: a Di chuyển dữ liệu từng hàng theo chiều ngang (gửi dữ liệu sang nút xử lý bên phải) và nhận dữ liệu từ nút xử lý bên trên. b Lặp lại bước a sqrt(p) lần để đảm bảo dữ liệu cuối cùng được đưa đến vị trí đúng. trên) và nhận kết quả từ nút xử lý bên phải. b Lặp lại bước a sqrt(p) lần để đảm bảo kết quả cuối cùng được trả về nút xử lý ban đầu.
7 Hoàn thành thuật toán và thu thập kết quả.
Hình 3.6 Hàm cài đặt Cannon
+ psa và psb là hai ma trận cần nhân
+ process: Số hiệu của tiến trình hiện tại
+ numprocs: Tổng số tiến trình trong communicator cartComm Đây là số lượng tiến trình mà thuật toán Cannon sẽ chạy trên
+ cartComm: Communicator 2D Cartesian mà các tiến trình sẽ tham gia Trong ngữ cảnh này, nó được tạo ra để định vị các tiến trình trên một lưới 2D.
Trong lưới 2D Cartesian, các số hiệu hàng xóm trái (left_neigh), phải (right_neigh), trên (up_neigh) và dưới (down_neigh) của tiến trình hiện tại được xác định thông qua hàm MPI_Cart_shift Những giá trị này rất quan trọng để gửi và nhận dữ liệu giữa các hàng xóm trong quá trình thực hiện thuật toán Cannon.
Bằng cách này, hàm cannonAlgorithm có thể thực hiện thuật toán Cannon dựa trên các thông tin về vị trí và hàng xóm của tiến trình trong lưới 2D Cartesian.
Hình 3.7 Hàm khởi tạo ma trận
Hình 3.9 Hàm kiểm tra số tiến trình là bình phương hoàn hảo
In this article, we explore the initialization of matrices in C++ using dynamic memory allocation The function `initializeMatrices` allocates memory for four matrices: `psa`, `psb`, `pra`, `prb`, and `c`, each sized at 1600 by 1600 Within the function, random integers between 1 and 100 are assigned to the elements of matrices `psa` and `psb`, while all elements of matrix `c` are initialized to zero This setup is essential for performing matrix operations efficiently in subsequent computations.
} for (int i = 0; i < n * n; i++) { pra[i] = psa[i]; prb[i] = psb[i];
} void deallocateMatrices(int*& psa, int*& psb, int*& pra, int*& prb, int*& c) { delete[] psa; delete[] psb; delete[] pra; delete[] prb; delete[] c;
} void printMatrix(int* matrix, int rows, int cols) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { cout