Ví dụ về lập trình song song với OpenMP

Một phần của tài liệu Song song hoá thuật toán Bames hut với OpenMP (Trang 39)

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 (adsbygoogle = window.adsbygoogle || []).push({});

Lê Thị Lan Phương 35

Chương 3: SONG SONG HÓA THUT 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 (adsbygoogle = window.adsbygoogle || []).push({});

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 dng khi xây dng 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 (adsbygoogle = window.adsbygoogle || []).push({});

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: (adsbygoogle = window.adsbygoogle || []).push({});

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. (adsbygoogle = window.adsbygoogle || []).push({});

• 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

Một phần của tài liệu Song song hoá thuật toán Bames hut với OpenMP (Trang 39)