Truy cập vào dữ liệu riêng của thread

Một phần của tài liệu Lập trình luồng (Trang 42 - 62)

Sau khi tạo ra một khóa, chúng ta có thể truy cập vào giá trị của chúng bằng cách sử dụng hai hàm: pthread_getspecific() và pthread_setspecific() . Hàm đầu tiên

được dùng để lấy giá trị của một khóa được đưa ra còn hàm sau được dùng để thiết lập giá trị của khóa được đưa ra. Giá trị của một khóa chỉ là một con trỏ kiểu void

Sinh viên: Cấn Việt Dũng 43 Lớp : K51CHTTT

dụng của những hàm này. Giả sử rằng ‘a_key’ là một biến khởi tạo kiểu

pthread_key_t để chứa khóa được tạo ra trước:

/* biến này được sử dụng để lưu giá trị trả về của hàm */ int rc;

/* định nghĩa một biến mà chúng ta sẽ lưu vào đó một vài dữ liệu, ví dụ là 1 số

nguyên */

int* p_num = (int*)malloc(sizeof(int)); if (!p_num) {

fprintf(stderr, "malloc: out of memory\n"; exit(1);

}

/* khởi tạo giá trị */

(*p_num) = 4;

/* bây giờ lưu giá trị này vào khóa */

/* chú ý rằng chúng ta không lưu ‘p_num’ vào khóa */

/* chúng ta chỉ lưu giá trị mà p_num trỏ tới */

rc = pthread_setspecific(a_key, (void*)p_num);

.

/* lấy giá trị của khóa a_key và in ra */ {

int* p_keyval = (int*)pthread_getspecific(a_key); if (p_keyval != NULL) {

Sinh viên: Cấn Việt Dũng 44 Lớp : K51CHTTT

printf("value of 'a_key' is: %d\n", *p_keyval); }

}

Chú ý rằng, nếu chúng ta thiết lập giá trị cho khóa trong một thread, và cố thử

lấy giá trị trong thread khác, chúng ta sẽ nhận được giá trị NULL, giá trị này là khác biệt cho mỗi thread. Cũng có hai trường hợp mà hàm pthread_getspecific() trả về

NULL:

- Khóa được cung cấp như tham số không hợp lệ ( ví dụ như khóa chưa được tạo).

- Giá trị của khóa là NULL. Điều này có thể là nó chưa được khởi tạo, hoặc

được đặt là NULL bởi lời gọi pthread_setspecific() trước.

2.5.4. Xóa dữ liệu trong thread

Hàm pthread_key_delete() có thểđược dùng để xóa khóa. Nhưng không được nhầm lẫn với tên của hàm này: nó không xóa được vùng nhớ liên quan tới khóa, cũng không gọi hàm hủy được định nghĩa trong khi khóa được tạo ra. Vì vậy, vẫn cần giải phóng vùng nhớ nếu cần thiết.

Sử dụng hàm này rất đơn giản. Giải sử list_key là một biến kiểu pthread_key_t trỏ tới một khóa đã được tạo, sử dụng hàm này như sau:

Int rc = pthread_key_delete(key);

Sinh viên: Cấn Việt Dũng 45 Lớp : K51CHTTT

CHƯƠNG 3: BÀI TOÁN CLOSEST_PAIR TRONG KHÔNG GIAN HAI

CHIỀU SỬ DỤNG MULTITHREADING 3.1. Giới thiệu bài toán

Cho trước N điểm trong hệ tọa độ Đề-các hai chiều. Tìm cặp điểm gần nhau nhất

trong N điểm nói trên. (Trong khóa luận này, tôi mới chỉ ra được khoảng cách ngắn nhất giữa hai điểm trong N điểm trên nhưng chưa chỉra được cặp điểm đó).

Để giải quyết bài toán này, có 2 thuật toán được đưa ra. Thuật toán thứ nhất, đó là ta đi duyệt tất cả các cặp điểm trong N điểm trên, so sanh khoảng cách rồi chọn ra hai điểm gần nhau nhất. Thuật toán này khá đơn giản, nhưng có độ phức tạp lớn: O(n2). Thuật toán thứ hai, còn được gọi là thuật toán chia để trị. Ý tưởng của thuật toán này là, ta chia N

điểm cho trước thành hai nửa, trái và phải, với sốđiểm tương đương nhau rồi ta tính toán

đệ qui khoảng cách ngắn nhất trên mỗi nửa đó. So với thuật toán thứ nhất, thuật toán này

có độ phức tạp nhỏhơn rất nhiểu: O(nlogn).

Cùng với cách cài đặt hai thuật toán trên, trong khóa luận tốt nghiệp này tôi đã cài

đặt song song hóa thuật toán thứhai để làm tăng hiệu năng tính toán. Cách song song hóa

thuật toán là, sau khi chia tập N điểm thành hai phần trái và phải, tôi tạo một thread để

tính toán nửa bên trái, như vậy, cùng với thread chính(của hàm main()), sẽ có một thread tính toán nửa bên trái chạy song song cùng với nó. Điều này làm tăng đáng kể hiệu năng

tính toán của chương trình. Cụ thểcác cách cài đặt được nêu rõ ở phần tiếp theo.

3.2. Các thuật toán khác nhau để giải bài toán tìm khoảng cách ngắn nhất giữa các cặp điểm trong N điểm cho trước. các cặp điểm trong N điểm cho trước.

- Thuật toán 1: ta duyệt tất cả các cặp điểm trong N điểm cho trước, so sánh khoảng cách giữa các cặp điểm đó rồi chọn ra khoảng cách ngắn nhất. Thuật toán này có

độ phức tạp tính toán O(n2). Mã lệnh thực hiện thuật toán: #include <stdlib.h> #include <stdio.h> #include <math.h> #define N 8000 struct coordinate{ float x; float y; };

Sinh viên: Cấn Việt Dũng 46 Lớp : K51CHTTT

/*--- ---

Ham tinh khoang cach giua 2 diem ---

---*/

float distance(struct coordinate point1, struct coordinate point2){

float temp1, temp2;

temp1 = point2.x - point1.x; temp2 = point2.y - point1.y;

return sqrt(temp1*temp1 +

temp2*temp2); };

/*--- ---

Ham tim gia tri nho nhat

--- ---*/

float min(float a, float b) { if (a < b) return a; else return b; }; /*--- ---

Ham truyen gia tri cho cac diem ---

---*/

void input(struct coordinate point[]) { int i = 0; float temp1,temp2; FILE *fp; if((fp=fopen("input.txt","r")) == NULL) {

printf("Cannot open file.\n"); } while(fscanf(fp, "%f %f", &point[i].x, &point[i].y) != eof()) i++; }; /*--- --- Ham chinh --- ---*/ int main() { int i,j; float result,temp;

struct coordinate point[N],point2[2]; input(point); result = distance(point[0],point[1]); point2[0] = point[0]; point2[1] = point[1]; for(i = 0; i < N; i++) for(j = i + 1; j < N; j++) {

Sinh viên: Cấn Việt Dũng 47 Lớp : K51CHTTT temp = distance(point[i],point[j]); if(temp < result){ point2[0] = point[i]; point2[1] = point[j]; result = temp; } }

printf("Ket qua la :%2.2f",result); printf("\nCap diem la: (%2.2f,%2.2f)

va (%2.2f,%2.2f)",

point2[0].x,point2[0].y,point2[1].x, point2[1].y);

}

- Thuật toán 2: ta thực hiện bài toán theo phương pháp chia để trị.

 Bước 1: Sắp xếp tăng dầntập N điểm cho trước theo tọa độ x. Ở đây tác giả khóa luận sử dụng thuật toán quicksort để sắp xếp.

 Bước 2: Gọi tập N điểm cho trước là tập S. Ta chia S thành hai tập con S1 và S2 (S1 gọi là nửa trái, S2 gọi là nửa phải) sao cho số điểm trong mỗi tập là tương đương nhau bằng đường thẳng L. Đường thẳng L được xác định bằng phương trình x = x_mid, với x_mid là tọa độ điểm chính giữa trong tập

S.

 Bước 3: Thực hiện tính toán đệ qui closest_pair đối với hai nửa trái và phải.

Giả sử tìm được khoảng cách ngắn nhất ở nửa trái là dL và ở nửa phải là dR.

 Bước 4: Tìm khoảng cách ngắn nhất delta giữa hai cặp điểm mà trong đó một điểm nằm bên trái đường thẳng L và một điểm nằm bên phải đường thằng L. Phần này là phần khó nhất trong bài toán. Giả sử ∂ = min(dL,dR).

Ta chọn tất cả những điểm ở S1 và S2 mà khoảng cách từ điểm đó tới đường thẳng L nhỏ hơn hoặc bằng ∂. Ta lưu những điểm thỏa mãn điều kiện đó

trong tập S1 vào mảng tempL[], trong tập S2 vào mảng tempR[]. Bây giờ ta đi tìm khoảng cách ngắn nhất giữa 2 điểm, với điều kiện trong 2 điểm này, 1

điểm thuộc tempL[] và 1 điểm thuộc tempR[]. Cách thực hiện là, với mỗi điểm pthuộc tempL[], ta chỉ xét những điểm ở tempR[] nằm trong hình chữ nhật có kích thước (∂,2*∂) với p là điểm góc trên trái của hình chữ nhật. Ta

có thể chỉ ra rằng nhiều nhất là có 6 điểm thuộc tempR[] thỏa mãn điều kiện

này.

Sinh viên: Cấn Việt Dũng 48 Lớp : K51CHTTT

Khi thực hiện cài đặt bằng phương pháp này, độ phức tạp tính toán của thuật toán là O(nlogn). Mã lệnh thực hiện thuật toán: #include <stdlib.h> #include <math.h> #include <stdio.h> #include <pthread.h> #include <sys/resource.h> #include <sys/time.h> #define N 8000 /*--- Struct luu toa do (x,y) cua 1 diem ---*/ struct coordinate{ float x; float y; }; /*--- Struct luu tham so truyen vao cho ham closest_pair

---*/ struct thamso{

int left ; int right ;

struct coordinate point[N];

};

/*--- Ham truyen gia tri cho cac diem

---*/ void input(struct coordinate point[]) { int i = 0; char s[81]; FILE *fp; fp = fopen("input.txt","r"); if(fp == NULL) {

printf("Cannot open file.\n");

} while(fgets(s,80,fp)!= NULL) { sscanf(s,"%f %f" ,&point[i].x,&point[i].y); i++; } }; /*---Ham lay thoi gian hien thoi toi mili giay

Sinh viên: Cấn Việt Dũng 49 Lớp : K51CHTTT double gettime() { struct timeval x; gettimeofday(&x, NULL); double t = (double)(x.tv_sec + x.tv_usec / 1000000.0); return (t); }; /*--- Ham tinh khoang cach giua 2 diem

---*/ float distance(struct coordinate

point1, struct coordinate

point2){

float temp1,temp2;

temp1 = point2.x - point1.x; temp2 = point2.y - point1.y; return sqrt(temp1*temp1 + temp2*temp2);

};

/*--- Ham tinh min cua 2 gia tri ---*/ float min(float a, float b) {

if (a < b) return a; else return b;

};

/*--- Ham sap xep cac diem tang dan theo toa do x

---*/ void quicksortX(struct coordinate

arr[], int low, int high) { int i = low; int j = high; float x = 0.0; float y = 0.0; float z = arr[(i + j) / 2].x; do { while(arr[i].x < z) i++; while(arr[j].x > z) j--; if(i <= j) { x = arr[i].x; y = arr[i].y; arr[i].x = arr[j].x; arr[i].y = arr[j].y; arr[j].x = x; arr[j].y = y; i++; j--; } } while(i <= j); if(low < j) quicksortX(arr, low, j); if(i < high) quicksortX(arr, i, high); };

Sinh viên: Cấn Việt Dũng 50 Lớp : K51CHTTT

/*--- Ham sap xep cac diem tang dan theo toa do y

---*/ void quicksortY(struct coordinate

arr[], int low, int high) { int i = low;

int j = high; float x = 0.0; float y = 0.0;

float z = arr[(low + high) / 2].y; do { while(arr[i].y < z) i++; while(arr[j].y > z) j--; if(i <= j) { x = arr[i].x; y = arr[i].y; arr[i].x = arr[j].x; arr[i].y = arr[j].y; arr[j].x = x; arr[j].y = y; i++; j--; } } while(i <= j); if(low < j) quicksortY(arr, low, j); if(i < high)

Một phần của tài liệu Lập trình luồng (Trang 42 - 62)

Tải bản đầy đủ (PDF)

(62 trang)