2.7.1 omp_hello.c
Chương trình minh họa hoạt động của các thread khi thực hiện song song.
• Biến tidđược khai báo là private, lưu ID của mỗi thread.
• Biến private nthreads cho biết số lượng thread tham gia vào quá trình song song.
2.7.2 Cách biên dịch
Tùy theo các nhà cung cấp và trình biên dịch hiện sử dụng, có thể có nhiều cách
để biên dịch một chương trình OpenMP.
Với hệ thống máy IBM, dùng cờ-qsmp=omp
Với hệ thống máy Intel, dùng cờ-openmp
Với hệ thống Compag, dùng cờ-omp
/* omp_hello.c */ #include <omp.h> int main () { int nthreads, tid;
/* Fork a team of threads giving them their own copies of variables */
#pragma omp parallel private(nthreads, tid) {
/* Obtain thread number */ tid = omp_get_thread_num();
printf("Hello World from thread = %d\n", tid); /* Only master thread does this */
if (tid == 0) {
nthreads = omp_get_num_threads();
printf("Number of threads = %d\n", nthreads); }
Lê Thị Lan Phương 34
Trên máy IBM AIX, để dịch chương trình “omp_hello.c”, dùng lệnh:
xlc_r –qsmp=omp omp_hello.c –o hello
Để thực hiện chương trình, gõ lệnh: ./hello
Nếu không chỉ rõ số lượng thread cần sử dụng để thực hiện quá trình song song, thì chương trình sẽ lấy số thread mặc định hiện có trong hệ thống kiến trúc bộ nhớ chia sẻ. Có thể xác định số thread cần thiết thông qua hàm thư viện omp_set_num_threads(int num_threads) hoặc truyền giá trị cho biến môi trường OMP_NUM_THREADS bằng lệnh: export OMP_NUM_THREADS
Giả sử, trong ví dụ trên đặt số thread là 4:
export OMP_NUM_THREADS=4
Xem trang
http://www.navo.hpc.mil/Resources/Hardware/Romulus_Users_Guide.html#ProgEnv
để biết thêm chi tiết về một số chỉ thị biên dịch.
2.7.3 Kết quả
Hello World from thread = 0 Number of threads = 4
Hello World from thread = 3 Hello World from thread = 1 Hello World from thread = 2
Lê Thị Lan Phương 35
Chương 3: SONG SONG HÓA THUẬT TOÁN BARNES-HUT
3.1 Treecode
Để tiến hành song song hóa thuật toán Barnes-Hut với bài toán N-body, ta xét chương trình treecode của J. Barnes làm ví dụ.
Treecode là một trong những chương trình mô phỏng bài toán N-body. Dựa trên nền tảng của thuật toán Barnes-Hut, treecode thực hiện nhanh hơn và kiểm soát lỗi tốt hơn so với các chương trình mô phỏng hệ N-body trước đó.
Như đã biết, trong thuật toán Barnes-Hut, sau khi xây dựng cây Quadtree (hoặc Octree), ta tiến hành duyệt cây để tính lực tác dụng lên từng hạt. Tuy nhiên, việc duyệt cây tốn rất nhiều thời gian. Treecode giảm thiểu chi phí cho duyệt cây bằng cách sử dụng tính chất: các hạt liền kề có danh sách các tương tác với nó là giống nhau. Ý tưởng này đã
được sử dụng trước đó để nhằm tăng tốc khi tính toán lực trên các máy vector [3], nhưng các chương trình đó chỉ đơn giản áp dụng tìm kiếm cây trong một khối hạt nhỏ. Treecode áp dụng cho tất cả các mức của cây.
Lực tác dụng lên các hạt được tính thông qua một vòng duyệt cây đệ quy. Quá trình duyệt cây đệ quy này lưu trữ và cập nhật danh sách các tương tác (interaction list). Tại mỗi mức của cây, hạt b (giả sử nằm trong ô c) được sử dụng để phân biệt với danh sách các tương tác mà b có thể có. Khi duyệt đệ quy tới hạt b, danh sách tương tác sẽ được sử dụng để tính lực hấp dẫn và thế năng tại hạt b.
3.1.1 Cấu trúc dữ liệu của cây
Cấu trúc dữ liệu chính được sử dụng trong treecode là cây Octree, bao gồm các body và các cell. Lá của cây lưu trữ thông tin của body. Các nút trong của cây là các cell. Tiến hành duyệt toàn bộ cây bắt đầu từ gốc của cây.
Lê Thị Lan Phương 36
Hình 15: Cấu trúc dữ liệu cây trong treecode (1)
Cấu trúc node biểu diễn các thông tin chung của body và cell. Theo lý thuyết, mỗi một thành phần của cây có thểđược biểu diễn là tổ hợp của body và cell. Nhưng cách biểu diễn đó là không hiệu quả, vì cấu trúc của body và cell đòi hỏi không gian bộ nhớ
khác nhau. Do vậy người ta sử dụng cấu trúc node để biểu diễn chung cho body và cell. Việc ép kiểu được sử dụng để chuyển con trỏ có kiểu tùy ý thành con trỏ trỏ tới node, body và cell.
typedef struct _node {
short type;
bool update;
real mass;
vector pos; struct _node *next; } node, *nodeptr;
#define Type(x) (((nodeptr) (x))->type) #define Update(x) (((nodeptr) (x))->update) #define Mass(x) (((nodeptr) (x))->mass) #define Pos(x) (((nodeptr) (x))->pos) #define Next(x) (((nodeptr) (x))->next)
Lê Thị Lan Phương 37
• Type(q) trả lại kiểu của node q, có giá trị là CELL hoặc BODY
• Update(q) có giá trị là boolean, cho biết q có cần cập nhật lực tương tác không?
• Next(q) là con trỏ, trỏ tới node tiếp theo của q, sau khi tất cả các con của q đã được duyệt.
• Mass(q) là khối lượng của hạt q hoặc là khối lượng của tất cả các hạt có trong cell q
• Pos(q) là vị trí của hạt q hoặc vị trí của tâm khối trong cell q Cấu trúc body biểu diễn các hạt. typedef struct { node bodynode; vector vel; vector acc; real phi; } body, *bodyptr;
#define Vel(x) (((bodyptr) (x))->vel) #define Acc(x) (((bodyptr) (x))->acc) #define Phi(x) (((bodyptr) (x))->phi)
Trong đó:
• Vel(b) là vận tốc của hạt b
• Acc(b) là gia tốc của hạt b
• Phi(b) là thế năng của hạt b
Cấu trúc cell biểu diễn các nút trong của cây
#define NSUB (1 << NDIM) typedef struct {
Lê Thị Lan Phương 38 #if !defined(QUICKSCAN) real rcrit2; #endif nodeptr more; union { nodeptr subp[NSUB]; matrix quad; } sorq; } cell, *cellptr; #if !defined(QUICKSCAN)
#define Rcrit2(x) (((cellptr) (x))->rcrit2) #endif
#define More(x) (((cellptr) (x))->more)
#define Subp(x) (((cellptr) (x))->sorq.subp) #define Quad(x) (((cellptr) (x))->sorq.quad)
Trong đó:
• Subq(c) là mảng các con trỏ trở tới các con của c
• More(c) là con trỏ trỏ tới con đầu tiên trong các con của c
• Quad(c) là ma trận quadrupole moments
• Rcrit2(c) là bình phương bán kính mà nếu nằm ngoài bán kính đó, ô cell c được coi như là một cell interaction.
Lê Thị Lan Phương 39
Hình 16: Cấu trúc dữ liệu cây trong treecode (2)
3.1.2 Các biến toàn cục
Treecode sử dụng các biến toàn cục. Biến toán cục được sử dụng chung cho tất cả
các tệp của chương trình và được khai báo với định nghĩa global. Định nghĩa global như
sau:
#define global extern
Các tham sốđầu vào:
• theta: cho biết độ chính xác khi tính toán lực. Tham số này không được xác định nếu bản QUICKSCAN được biên dịch
• options: là một chuỗi các tùy chọn để điều khiển thời gian chạy
• usequad: cờ cho biết có sử dụng quadrupole correctión hay không?
Các biến được sử dụng khi xây dựng cây:
• root: con trỏ trỏ tới root cell
• rsize: kích cỡ của root cell
• ncell: số các cell được sử dụng để xây dựng cây
• tdepth: chiều cao của cây
• cputree: thời gian CPU đòi hỏi để xây dựng cây
Lê Thị Lan Phương 40
• actmax:độ dài lớn nhất của danh sách active trong khi tính lực
• nbbcalc: số các tương tác giữa các hạt với nhau
• nbccalc: số các tương tác giữa các hạt và các cell
• cpuforce: thời gian CPU cần để tính lực
3.2 Thử nghiệm và đánh giá hiệu năng của treecode 3.2.1 Thử nghiệm chương trình treecode 3.2.1 Thử nghiệm chương trình treecode
Toàn bộ mã chương trình treecode do J. Barnes viết có thể được download tại trang web http://www.ifa.hawaii.edu/~barnes/treecode/treeguide.html
Treecode được viết bằng ngôn ngữ C (ANSI C). Giả sử chương trình được biên dịch bởi trình biên dịch của hệđiều hành LINUX.
Download file treecode.tar.gz tại trang web trên. Để thực hiện chương trình, copy file vào thư mục riêng, rồi thực hiện lệnh gunzip để giải nén tệp.
$ gunzip treecode.tar.gz $ tar xvf treecode.tar
Thư mục sau đó sẽ chứa các file .c , .h và Makefile
Trước khi biên dịch, có thể cần phải chỉnh sửa một số thông tin trong Makefile tùy theo kiến trúc máy tính và trình biên dịch hiện đang sử dụng. Ở đây, ta sửa lại thông tin trong Makefile bằng cách thêm tùy chọn –pg vào các cờ biên dịch: CCFLAGS và cờ
LDFLAGSđể khi thực hiện chương trình sẽ sinh ra file gmon.out
Tùy chọn biên dịch trong Makefile được sửa lại như dưới đây:
# Compiler options. # LINUX:
CCFLAGS = -pg -DLINUX LDFLAGS = -pg
OPTFLAG = -O3
Lê Thị Lan Phương 41
$ make treecode
Thực hiện chương trình bằng ./treecode [tham số]
Có thể xem các tham số bằng câu lệnh: ./treecode –help
treecode Hierarchical N-body code (theta scan) in= Input file with initial conditions out= Output file of N-body frames
dtime=1/32 Leapfrog integration timestep eps=0.025 Density smoothing length
theta=1.0 Force accuracy parameter usequad=false if true, use quad moments options= Various control options tstop=2.0 Time to stop integration dtout=1/4 Data output timestep
nbody=4096 Number of bodies for test run seed=123 Random number seed for test run save= Write state file as code runs restore= Continue run from state file VERSION=1.4 Joshua Barnes February 21 2001
Khi thực hiện chương trình, kết quả của quá trình tính toán sẽđược hiển thị ra màn hình, có dạng như sau:
Lê Thị Lan Phương 42
3.2.2 Đánh giá hiệu năng
Mặc dù treecode là một cải tiến của thuật toán Barnes-Hut, với tốc độ tính toán lực nhanh hơn và vấn đề kiểm soát lỗi tốt hơn so với các chương trình trước đó, song vấn
đề duyệt cây vẫn chiếm đa số thời gian thực hiện chương trình.
Có thể xem thời gian thực hiện các hàm trong toàn bộ chương trình thông qua profile của nó. Thực hiện lệnh gprof với chương trình treecode để xem thông tin profile về chương trình như sau:
gprof treecode gmon.out > treecode.out
Kết quả hiển thị trong file treecode.out có dạng:
Hierarchical N-body code (theta scan)
nbody dtime eps theta usequad dtout tstop 4096 0.03125 0.0250 1.00 false 0.25000 2.0000 rsize tdepth ftree actmax nbbtot nbctot CPUfc 64.0 13 3.050 1114 1051990 1417390 0.003 time |T+U| T -U -T/U |Vcom| |Jtot| CPUtot 0.000 0.24032 0.25082 0.49114 0.51069 0.00000 0.00576 0.004 rsize tdepth ftree actmax nbbtot nbctot CPUfc 64.0 12 3.108 1121 1054863 1419799 0.003 time |T+U| T -U -T/U |Vcom| |Jtot| CPUtot 0.031 0.24028 0.25075 0.49104 0.51066 0.00001 0.00576 0.007 rsize tdepth ftree actmax nbbtot nbctot CPUfc 64.0 13 3.057 1108 1040044 1422316 0.003 time |T+U| T -U -T/U |Vcom| |Jtot| CPUtot 0.062 0.24029 0.25069 0.49098 0.51059 0.00001 0.00576 0.011
Lê Thị Lan Phương 43
Kết quả này có được khi biên dịch và thực hiện chương trình trên máy Intel với 1 CPU, Pentium 4 CPU 2.26GHz, 240MB RAM, hệ điều hành LINUX. Như vậy, qua kết quả trên ta thấy hàm walktree chiếm đến 96.02% tổng số thời gian thực hiện cả chương trình, trong khi phần trăm thời gian thực hiện các hàm khác là rất nhỏ.
Do vậy, tuy thời gian thực hiện treecode có nhanh hơn và vấn đề kiểm soát lỗi là tốt hơn so với các chương trình mô phỏng bài toán N-body trước đó, song để tối ưu hóa chương trình treecode, ta tiến hành thử nghiệm song song hóa chương trình với OpenMP trên máy Intel 4 CPU nhằm tăng hiệu năng tính toán.
3.3 Song song hóa treecode với OpenMP 3.3.1 Môi trường thực hiện song song 3.3.1 Môi trường thực hiện song song
Thực hiện song song hóa thuật toán treecode trên môi trường Intel (R) Xeon (TM) 4 CPU 2.40 GHz. Thông tin chi tiết về cấu hình 1 CPU trên máy Intel được cho dưới đây:
processor : 0
vendor_id : GenuineIntel cpu family : 15
model : 2
model name : Intel(R) Xeon(TM) CPU 2.40GHz stepping : 7
Flat profile:
Each sample counts as 0.01 seconds.
% cumulative self self total time seconds seconds calls s/call s/call name 96.02 129.09 129.09 65 1.99 1.99 walktree 0.96 130.37 1.29 2466730 0.00 0.00 subindex 0.95 131.65 1.28 65 0.02 0.02 diagnostics 0.76 132.68 1.03 266240 0.00 0.00 loadbody 0.57 133.44 0.76 65 0.01 0.01 hackcofm 0.21 133.72 0.28 65 0.00 0.00 threadtree 0.19 133.97 0.25 65 0.00 0.00 newtree 0.13 134.15 0.18 64 0.00 2.05 stepsystem 0.10 134.28 0.13 65 0.00 0.00 expandbox 0.05 134.35 0.07 130637 0.00 0.00 makecell 0.03 134.39 0.04 69477 0.00 0.00 xrandom 0.01 134.41 0.02 130637 0.00 0.00 setrcrit 0.01 134.43 0.02 8192 0.00 0.00 fpickshell 0.01 134.45 0.02 65 0.00 2.05 treeforce 0.01 134.46 0.01 1 0.01 0.07 testdata
Lê Thị Lan Phương 44
cpu MHz : 2394.914 cache size : 512 KB Physical processor ID: 0 Number of siblings : 2 fdiv_bug : no hlt_bug : no f00f_bug : no coma_bug : no fpu : yes fpu_exception : yes cpuid level : 2 wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm
bogomips : 4750.85
3.3.2 Thực hiện song song
Theo đánh giá hiệu năng của treecode ở mục 3.2.2, ta thấy phần lớn thời gian chương trình dành cho việc thực hiện hàm walktree. Để tăng hiệu năng tính toán của treecode, ta tiến hành song song hóa treecode bằng cách song song hóa các hàm trên.
Khó khăn gặp phải trong khi tiến hành song song hóa treecode đó là sự phụ thuộc vào chương trình dịch. Với các trình biên dịch của các kiến trúc máy tính khác nhau sẽ
cho thời gian thực hiện từng hàm con trong chương trình treecode là khác nhau.
Ví dụ với trình biên dịch của máy IBM eServer Cluster 1600, hệ điều hành AIX5.2 với cấu hình như sau:
• 5 node tính toán pSeries 655, mỗi node gồm 8 CPU Power 4+ 64 bit RISC 1.7 GHz của IBM; cache 5.6MB ECC L2, 128MB ECC L3, băng thông: 72.3 GBps; 32GB RAM, băng thông bộ nhớ 51.2 GBps; 6x36 GB HDD. Năng lực tính toán tổng cộng khoảng 240 GFlops (mở rộng tối đa 768 GFlops/16 node).
• 1 node quản lý CSM p630: Power4+ 64 bit 1.2 GHz; cache 1.5 MB ECC L2, 8MB ECC L3, băng thông: 12.8 GBps; 1GB RAM, băng thông: 6.4 GBps; 6x36 GB HDD, DVD ROM.
• 1 node điều khiển phần cứng HCM: Intel Xeon 3.06 GHz, 1GB RAM, 40 GB HDD, DVD RAM.
Lê Thị Lan Phương 45
• Các node được kết nối với nhau thông qua HPS (High Performance Switch – Switch hiệu năng cao), băng thông 2GBps và GEthernet.
• Hệ thống lưu trữ chung: IBM DS4400 và EXP700 kết nối với cụm IBM 1600 thông qua cáp quang với băng thông 2Gbps.
• Các node chạy HĐH AIX 5L phiên bản 5.2 Kết quả profile của treecode trên IBM AIX sẽ là:
Với trình biên dịch của Intel (R) Xeon (TM) 4 CPU 2.40 GHz, thì phần trăm thời gian thực hiện các hàm của treecode là:
% cumulative self self total time seconds seconds calls ms/call ms/call name 42.3 13.85 13.85 .sqrt [8] 34.8 25.23 11.38 532480 0.02 0.02 .sumnode [9] 7.6 27.73 2.50 .__mcount [11] 5.4 29.50 1.77 161645903 0.00 0.00 .sqrtf [12] 4.0 30.81 1.31 16072949 0.00 0.00 .accept [13] 2.6 31.65 0.84 570149 0.00 0.03 .walktree_13_6 <cycle 1> [7] 0.8 31.91 0.26 .qincrement [15] 0.5 32.09 0.18 65 2.77 2.77 .diagnostics [18] 0.4 32.22 0.13 2480994 0.00 0.00 .subindex [19] 0.4 32.34 0.12 .__stack_pointer [20] 0.4 32.46 0.12 .qincrement1 [21] 0.3 32.55 0.09 266240 0.00 0.00 .loadbody [16] 0.2 32.61 0.06 65 0.92 1.25 .hackcofm [22] 0.1 32.64 0.03 65 0.46 0.46 .threadtree [25]
Lê Thị Lan Phương 46
Như vậy, với các trình biên dịch khác nhau, thời gian thực hiện các hàm của treecode là hoàn toàn khác. Vì vậy, việc đánh giá hàm nào tốn nhiều thời gian nhất cũng như cần phải tiến hành song song hóa như thế nào là vấn đề gặp nhiều khó khăn.
3.3.2.1 Phân tích hàm walktree
Hàm walktree là hàm đệ quy chính dùng trong khi tính lực. Nguyên mẫu của nó có dạng
void walktree(nodeptr *aptr, nodeptr *nptr, cellptr cptr, cellptr bptr,nodeptr p, real psize, vector pmid);
Hàm walktree tính lực hấp dẫn lên tất cả các hạt có trong node p thông qua việc duyệt đệ quy p và các con của nó. Tại mỗi thời điểm trong lượt duyệt đệ quy, thông tin của các node từ gốc tới p được lưu trữ trong một tập các node. Tập đó chính là tập các tương tác. Tập này được chia thành 2 tập cell và body riêng biệt, được trỏ bởi các con trỏ
tương ứng là cptr và bptr. Phần còn lại của cây được biểu diễn bởi một tập các active node, bao gồm node p và các node xung quanh nó trong không gian. Con trỏ trỏ tới các node này được lưu vào mảng nằm giữa aptr và nptr. Node p có kích thước là psize và vị
trí là pmid.
Trong vòng lặp chính, walktree duyệt qua tất cả các active node của p, kiểm tra xem node nào sẽđược thêm vào danh sách tương tác, và node nào gần với p đến mức phải