Kết quả thử nghiệm

Một phần của tài liệu LUẬN VĂN: NGHIÊN CỨU HỆ THỐNG CỤM MÁY TÍNH XỬ LÝ SONG SONG ROCKS VÀ ỨNG DỤNG pptx (Trang 98 - 186)

4. 15 Phƣơng hƣớng xây dựng một ứng dụng MPI

5.4.Kết quả thử nghiệm

Nếu video đầu vào có tên là myfile thì video kết quả sẽ có tên là out-myfile. Với 4 video ban đầu, ứng dụng cho kết quả là 4 video khác trong cùng thƣ mục.

87

88

89

CHƢƠNG 6. KẾT LUẬN

Khóa luận đã trình bày những kiến thức cơ bản nhất về xử lý song song nói chung và xử lý song song phân cụm nói riêng. Về Rocks, khóa luận đã có hƣớng dẫn cài đặt chi tiết, cùng các nghiên cứu từ mức tổng quan đến mức kiến trúc hệ thống. Khóa luận cũng đã hƣớng dẫn chi tiết về các tác vụ quản trị căn bản và quan trọng nhất với cluster Rocks.

Về mặt ứng dụng, khóa luận đã trình bày cách thức lập trình song song sử dụng MPI và phƣơng hƣớng xây dựng một ứng dụng MPI hiệu quả, tận dụng đƣợc tài nguyên hệ thống, đồng thời xây dựng cụ thể một vài ứng dụng MPI và thử nghiệm thực tế thành công.

Việc cài đặt và quản trị thành công một cụm máy tính Rocks, cũng nhƣ xây dựng thành công các ứng dụng xử lý song song bằng MPI đã cho thấy nghiên cứu và triển khai Rocks trong thực tế là hoàn toàn khả thi, đặc biệt trong điều kiện các doanh nghiệp Việt Nam còn chủ yếu làm gia công phần mềm thay vì cung cấp các dịch vụ tính toán hƣớng ngƣời dùng.

Rocks cung cấp kèm theo rất nhiều Roll, nhƣng do thời gian có hạn nên khóa luận chƣa thể nghiên cứu hết về các Roll này. Mặt khác, việc không triển khai đƣợc Rocks trong điều kiện thực tế cũng là một hạn chế khác của khóa luận.

Trong thời gian tới, chúng tôi dự kiến sẽ tiếp tục nghiên cứu sâu hơn đề tài theo các hƣớng nhƣ:

 Nghiên cứu phát triển một Roll mới từ đầu.

 Nghiên cứu về các Roll khác mà Rocks cung cấp kèm theo.

 Nghiên cứu cách giải quyết các bài toán kinh điển bằng MPI, nhƣ bài toán ngƣời đƣa hàng, bài toán tìm kiếm trên một cơ sở dữ liệu đủ lớn, …

 Nghiên cứu sâu hơn về lý thuyết xử lý song song và các công nghệ xử lý song song.

90

PHỤ LỤC 1. SƠ LƢỢC VỀ CÁCH PHÁT TRIỂN ROLL MỚI

Phần trình bày dƣới đây sẽ bàn sơ lƣợc về cách phát triển một Roll mới từ mã nguồn / package có sẵn. Công cụ để minh họa chính là mã nguồn của Rocks 5.2.

Download mã nguồn Rocks 5.2

Để lấy mã nguồn của Rocks 5.2, khởi động root terminal và thực thi command: hg clone http://fyp.rocksclusters.org/hg/rocks-5.2

Toàn bộ mã nguồn của Rocks 5.2 nặng cỡ khoảng 2GB, nếu đây là lần đầu tiên thực thi command thì quá trình thực thi sẽ rất lâu, từ vài chục phút đến vài tiếng. Thực chất, hg clone là command dùng để tạo một bản copy của một repository nào đó bằng cách cập nhật các thay đổi từ repository đó vào bản copy cục bộ. Vì vậy trong những lần thực thi sau, thời gian thực thi sẽ ngắn hơn nhiều, do cập nhật các thay đổi nhanh hơn nhiều so với việc cập nhật toàn bộ repository. Output của command trên có dạng:

Hình 51 – Output của hg clone

91

Hình 52 – Repository cục bộ

92

Hình 53 – Thư mục scratch của các Roll

93

Hình 54 – Thư mục scratch của Roll java

Thƣ mục Nodes

Thƣ mục Nodes chứa các file XML, đây là các file cấu hình của Roll. Các file này định nghĩa các package cần cài đặt và các service tƣơng ứng của chúng. Ví dụ, dòng sau đây quy định package jdk sẽ đƣợc cài đặt:

<package os=“linux”>jdk</package>

Thẻ <post></post> quy định cách các package này đƣợc cấu hình sau khi chúng đƣợc cài đặt. Ví dụ: (adsbygoogle = window.adsbygoogle || []).push({});

<post os="linux">

/usr/sbin/useradd -M -u405 -c "JBoss" -d /opt/jboss jboss /usr/sbin/useradd -M -u412 -c "Tomcat" -d /opt/tomcat tomcat

chown -R 405.405 /opt/jboss chown -R 412.412 /opt/tomcat

94

chown -R 412.412 /opt/tomcat-*

<!--

libgcj lays down a dummy 'java' executible, so let's nuke it. this makes sure that the real java (included in this roll) is used -->

rm -f /usr/bin/java

<file name="/etc/man.config" mode="append"> MANPATH /usr/java/jdk1.5/man

</file>

<!-- configure mod_jk -->

<file name="/etc/httpd/conf.d/mod_jk.conf"> LoadModule jk_module modules/mod_jk.so

JkWorkersFile /etc/httpd/conf/workers.properties

# Where to put jk logs

JkLogFile /var/log/httpd/mod_jk.log

# Set the jk log level [debug/error/info] JkLogLevel info

# Select the log format

JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "

# JkOptions indicate to send SSL KEY SIZE,

JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories

# JkRequestLogFormat set the request format JkRequestLogFormat "%w %V %T"

</file>

<file name="/etc/httpd/conf/workers.properties"> workers.java_home=/usr/java/jdk1.5

95

</file>

</post>

Thƣ mục graphs

Thƣ mục graphs chứa file graphs/default/<roll>.xml. Với Roll java bên trên, file này là graphs/default/java.xml. File này định nghĩa cách các file trong thƣ mục nodes đƣợc liên kết với nhau trong sơ đồ cơ sở (Kickstart Graph). Ví dụ, với phần sơ đồ cơ sở dƣới đây:

Hình 55 – Một phần sơ đồ cơ sở

Cạnh nối đi từ nút frontend đến nút intel là kết quả của đoạn mã dƣới đây trong file <roll>.xml: (adsbygoogle = window.adsbygoogle || []).push({});

<edge from="frontend"> <to>intel</to>

</edge>

Thêm một package nhƣ thế nào

Giả sử Roll ta đang cần phát triển có tên là myroll. Ta cần add thêm 4 package cho Roll là: pkg-one, pkg-two, pkg-three, pkg-four. Giả sử cần add pkg-one và pkg-two vào máy frontend và pkg-three và pkg-four vào các máy compute.

Trƣớc hết, tạo file myroll/nodes/myroll-frontend.xml. File này có dạng: <?xml version="1.0" standalone="no"?>

<kickstart>

96 My customized roll. </description> <changelog> </changelog> <package>pkg-one</package> <package>pkg-two</package> <post>

<!-- configuration scripts for post installation --> </post>

</kickstart>

Sau đó tạo file myroll/nodes/myroll-compute.xml: <?xml version="1.0" standalone="no"?> <kickstart> <description> My customized roll. </description> <changelog> </changelog> <package>pkg-three</package> <package>pkg-four</package> <post>

<!-- configuration scripts for post installation --> </post>

97

Cuối cùng là tạo file myroll/graphs/default/myroll.xml để nối các file node vào sơ đồ cơ sở:

<?xml version="1.0" standalone="no"?> <graph> <description> My customized roll. </description> <changelog> </changelog> <edge from="frontend"> <to>myroll-frontend</to> </edge> <edge from="compute"> <to>myroll-compute</to> </edge> </graph> Sơ lƣợc hoạt động

File graph và các file node là cơ sở để hình thành nên sơ đồ cơ sở. Trong quá trình cài đặt, trình cài đặt sẽ dựa vào sơ đồ cơ sở của từng Roll để sinh ra file cơ sở. Từ file cơ sở này, trình cài đặt sẽ biết đƣợc cần phải cài đặt những package nào cho từng máy đối với Roll hiện hành.

Quá trình duyệt sơ đồ cơ sở diễn ra nhƣ sau:

 Trình cài đặt đọc file graph để duyệt trên sơ đồ cơ sở,

 Từ sơ đồ cơ sở, trình cài đặt sẽ xem xét các file node cần thiết cho máy đang cài đặt hiện hành, từ đó đọc đƣợc các thông tin cần thiết về các package cần cài đặt cho máy đó để sinh ra file cơ sở.

98

Với roll myroll bên trên, trong quá trình cài đặt máy frontend, file graph và file node myroll-frontend.xml sẽ đƣợc duyệt. Tƣơng tự, trong quá trình cài đặt các máy compute, file graph và file nodes myroll-compute.xml sẽ đƣợc duyệt.

99

PHỤ LỤC 2. LIÊN LẠC GIỮA CÁC TIẾN TRÌNH MPI

Nhƣ đã giới thiệu trong chƣơng 4, cặp hàm MPI_Send và MPI_Recv là cặp hàm cơ bản để liên lạc giữa các tiến trình MPI. Do tính chất đồng bộ của cặp hàm này nên các nhà phát triển phải cẩn thận khi thiết kế các ứng dụng MPI để tránh tình trạng deadlock.

Ứng dụng dƣới đây đƣợc dùng để minh họa cho việc liên lạc giữa các tiến trình MPI sử dụng MPI_Send và MPI_Recv. Tiến trình có rank i sẽ gửi một số nguyên đến tiến trình có rank (i + 1) % size, với size là số lƣợng tiến trình. Khi số nguyên đƣợc nhận bởi tiến trình có rank 0, giá trị của nó đƣợc giảm đi 1 rồi đƣợc tiếp tục gửi đi theo quy tắc trên. Nếu giá trị của số nguyên là 0 thì tiến trình tƣơng ứng sẽ thoát sau khi gửi và nhận thành công.

Dƣới đây là mã nguồn ứng dụng. #include <stdio.h>

#include "mpi.h"

int main(int argc, char* argv[]) {

int myRank, numProcs; int num, tag, next, from; MPI_Status status;

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORLD, &numProcs); MPI_Comm_rank(MPI_COMM_WORLD, &myRank); (adsbygoogle = window.adsbygoogle || []).push({});

tag = 201;

next = (myRank + 1) % numProcs;

from = (myRank + numProcs - 1) % numProcs;

if (myRank == 0) { num = 2;

fprintf(stdout, "Process %d sending %d to %d\n", myRank, num, next);

100

}

do {

MPI_Recv(&num, 1, MPI_INT, from, tag, MPI_COMM_WORLD, &status);

fprintf(stdout, "Process %d received %d\n", myRank, num);

if (myRank == 0) { --num;

printf("Process 0 decremented num\n"); }

fprintf(stdout, "Process %d sending %d to %d\n", myRank, num, next);

MPI_Send(&num, 1, MPI_INT, next, tag, MPI_COMM_WORLD); } while (num > 0);

fprintf(stdout, "Process %d exiting\n", myRank);

if (myRank == 0) {

MPI_Recv(&num, 1, MPI_INT, from, tag, MPI_COMM_WORLD, &status);

}

MPI_Finalize(); return 0;

}

Do tính chất đồng bộ của MPI_Send và MPI_Recv nên cách thử nghiệm ứng dụng tốt nhất là chạy với n tiến trình (n ≥ 2) trên cùng một máy.

101

102

PHỤ LỤC 3. SỬ DỤNG MPI ĐỂ TÍNH TÍCH PHÂN

Dƣới đây là một ứng dụng MPI đƣợc viết nhằm giải quyết bài toán tính diện tích của hình thang cong nằm dƣới parabol với . Mỗi máy con tham gia tính toán sẽ chịu trách nhiệm tính diện tích của một hình thang cong con. Kết quả sau đó sẽ đƣợc cộng lại để cho ra đáp số cuối cùng. #include "mpi.h" #include <stdio.h> #define NUM_RECTS 50 #define LOWER_BOUND 2.0 #define UPPER_BOUND 5.0

int main(int argc, char* argv[]) {

int numProcs, myRank;

int destination, source, tag; MPI_Status status;

int i; (adsbygoogle = window.adsbygoogle || []).push({});

double area, at, height, lower, width, total, range;

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORLD, &numProcs); MPI_Comm_rank(MPI_COMM_WORLD, &myRank);

range = (UPPER_BOUND - LOWER_BOUND) / numProcs; width = range / NUM_RECTS;

lower = LOWER_BOUND + range * myRank;

area = 0.0;

for (i = 0; i < NUM_RECTS; i++) {

at = lower + i * width + width / 2.0; height = at * at;

103 } tag = 0; if (myRank == 0) { total = area;

for (source = 1; source < numProcs; source++) {

MPI_Recv(&area, 1, MPI_DOUBLE, source, tag, MPI_COMM_WORLD, &status);

total = total + area; }

fprintf(stdout, "The area from %f to %f is: %f\n", LOWER_BOUND, UPPER_BOUND, total);

} else {

destination = 0;

MPI_Send(&area, 1, MPI_DOUBLE, destination, tag, MPI_COMM_WORLD); } MPI_Finalize(); return 0; }

Lƣu với tên mpiintegralx2.c, biên dịch và chạy ta sẽ có output:

Hình 57 – Tính tích phân

Nếu chúng ta tính bằng công thức tính tích phân, thì giá trị diện tích của hình thang cong trong đoạn [2, 5] sẽ là | .

104

PHỤ LỤC 4. SỬ DỤNG MPI ĐỂ TÍNH TOÁN SỐ PI

Trong phần dƣới đây chúng ta sẽ nghiên cứu thêm về MPI qua ví dụ về tính toán số PI. Tính toán số PI không chỉ là bài toán mang tính thực tế cao, nó còn là một trong những ví dụ kinh điển để minh họa cho các công nghệ tính toán song song. Nguyên nhân là với một chƣơng trình tính toán số PI, ngƣời phát triển không cần quan tâm đến vấn đề “cân bằng tải”, lại giảm thiểu đƣợc việc liên lạc giữa các tiến trình và kiểm tra đƣợc kết quả mà không cần dùng máy vi tính. Để tính PI có nhiều công thức khác nhau. Hiện tại có những công thức có thể giúp tính ra số PI với hàng chục nghìn chữ số đáng tin trong khoảng thời gian tính bằng giờ [15]. Trong chƣơng trình sẽ trình bày bên dƣới, chúng ta sẽ sử dụng công thức tích phân:

( )| ( ) ( ) ( )

do đó công việc còn lại của ta chỉ là tính tích phân bên trái. Công thức này rất dễ tính nhờ định nghĩa của tích phân. Ta sẽ chia đƣờng cong

trong đoạn từ 0 đến 1 ra làm các đoạn con, và tính diện tích của các hình chữ nhật ứng với các đoạn con này. Diện tích của hình thang cong giới hạn bởi

đƣợc coi nhƣ xấp xỉ bằng tổng diện tích của

các hình chữ nhật. Số lƣợng các đoạn con càng nhiều, độ chính xác của kết quả càng cao.

Hình 58 – Tính toán số PI (adsbygoogle = window.adsbygoogle || []).push({});

105

Để thấy đƣợc mối quan hệ giữa số lƣợng các đoạn con n và độ chính xác của kết quả, chúng ta sẽ thiết kế chƣơng trình sao cho tiến trình chủ (master) chấp nhận một tham số từ phía ngƣời dùng, truyền tham số này đến các tiến trình con (slave). Kết quả cuối cùng này sẽ đƣợc so sánh với số 3.141592653589793238462643 để biết độ chính xác.

Chƣơng trình bên dƣới có một số điểm cần lƣu ý nhƣ sau:

Sử dụng phƣơng pháp gửi thông điệp hàng loạt nhờ hàm MPI_Bcast. MPI_Bcast gửi một thông điệp đến tất cả các tiến trình khác trong nhóm. Signature của hàm này là:

int MPI_Bcast(void *address, int count, MPI_Datatype dataType, int root, MPI_Comm communicator)

Trong đó, 3 tham số đầu tiên xác định thông điệp cần truyền đi (địa chỉ bắt đầu của thông điệp trong bộ đệm (address), kiểu dữ liệu của thông điệp (dataType) và số lƣợng thành tố có kiểu dữ liệu đã xác định trong bộ đệm (count). Tham số root cho biết rank của tiến trình truyền. Tham số cuối cùng xác định bộ liên lạc chứa các tiến trình nhận.

Lƣu ý rằng, hàm nhân tƣơng ứng của hàm gửi MPI_Bcast cũng chính là MPI_Bcast, tƣơng tự nhƣ hàm nhận tƣơng ứng của hàm gửi MPI_Send là MPI_Recv.

Sử dụng hàm MPI_Reduce để tính toán kết quả cuối cùng, thay vì truyền thủ công giá trị tính toán từ các tiến trình con (slave) về tiến trình cha (master) rồi tính tổng. Signature của hàm này là:

int MPI_Reduce(void *sendbuf, void *recvbuf, int count, MPI_Datatype dataType, MPI_Op op, int root, MPI_Comm communicator)

Trong đó, 3 tham số sendbuf, count và dataType định nghĩa thông điệp mà mỗi tiến trình con cần truyền đến tiến trình cha (ý nghĩa tƣơng tự nhƣ trên). Tham số recvbuf định nghĩa địa chỉ bộ đệm sẽ đƣợc dùng để nhận. Tham số op định nghĩa toán tử thao tác trên các thông điệp. Tham số root định nghĩa rank của tiến trình cha. Tham số communicator ý nghĩa tƣơng tự nhƣ trên.

106 Bảng 2 – Các hằng số toán tử Hằng số Ý nghĩa MPI_MAX Tìm số lớn nhất MPI_MIN Tìm số nhỏ nhất MPI_SUM Tính tổng MPI_PROD Tính tích MPI_LAND Tính AND (logic) MPI_BAND

Tính AND (trên bit) MPI_LOR Tính OR (logic) MPI_BOR Tính OR (trên bit) MPI_LXOR Tính XOR (logic) MPI_BXOR

Tính XOR (trên bit) MPI_MINLOC

Tính giá trị nhỏ nhất của phần tử thứ nhất của một struct (minimum), đồng thời trả về phần tử thứ 2 tƣơng ứng (location). Nếu tất cả các phần tử thứ nhất đều bằng nhau thì location đƣợc tính bằng giá trị nhỏ nhất trong số các phần tử thứ hai. Xem [33] để rõ hơn.

MPI_MAXLOC

Tính maximum và location, tƣơng tự nhƣ trên.

Mỗi tiến trình sẽ tính toán một số lƣợng gần nhƣ nhau các hình chữ nhật con “rời rạc”, nghĩa là các hình chữ nhật con này không nằm liên tiếp. Cụ thể, nếu có 2 tiến trình tính diện tích của 10 hình chữ nhật con, thì tiến trình 1 sẽ tính diện tích của các hình chữ nhật số 1, 3, 5, 7, 9, và tiến trình thứ 2 sẽ tính diện tích của các hình chữ nhật số 2, 4, 6, 8, 10. Mục đích là để tránh các phép toán nhân chia không cần thiết để tính “khoảng”

107

tính toán cho mỗi tiến trình, đồng thời tránh việc sử dụng thêm biến trung gian để lƣu lại các giá trị “khoảng” này.

#include "mpi.h" #include <stdio.h> #include <math.h>

/*

* Ung dung tinh toan so PI */

int main(int argc, char *argv[]) {

int myRank, numProcs;

int n, i;

// Gia tri PI voi 25 chu so

double PI25DT = 3.141592653589793238462643; double mypi, pi, h, sum, x;

MPI_Init(&argc, &argv);

MPI_Comm_size(MPI_COMM_WORLD, &numProcs); MPI_Comm_rank(MPI_COMM_WORLD, &myRank);

while (1) { (adsbygoogle = window.adsbygoogle || []).push({});

if (myRank == 0) {

fprintf(stderr, "Enter the number of intervals (0 quits): ");

scanf("%d", &n); }

MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); if (n == 0) {

break; } else {

108

sum = 0.0;

for (i = myRank + 1; i <= n; i += numProcs) { x = h * ((double) i - 0.5);

sum += (4.0 / (1.0 + x * x)); }

mypi = h * sum;

MPI_Reduce(&mypi, &pi, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);

if (myRank == 0) { fprintf(

stdout,

"pi is approximately %.16f, Error is %.16f\n", pi, fabs(pi - PI25DT)); } } } MPI_Finalize(); return 0; }

TÀI LIỆU THAM KHẢO

Tiếng Việt

[1] Nguyễn Phú Bình. Kiến trúc các hệ thống tính toán. Chƣơng 1.http://www.ebook.edu.vn/?page=1.39&view=1250.

[2] Siêu máy tính “Made In Vietnam”. http://www.pcworld.com.vn/articles/quan-ly/giai-phap-

Một phần của tài liệu LUẬN VĂN: NGHIÊN CỨU HỆ THỐNG CỤM MÁY TÍNH XỬ LÝ SONG SONG ROCKS VÀ ỨNG DỤNG pptx (Trang 98 - 186)