2011-12-31 58 views
11

Sau rất nhiều tìm kiếm cho việc thực hiện quicksort song song trong c, tôi chuẩn bị đi sâu vào và tự viết mã. (Tôi cần sắp xếp một mảng khoảng 1 triệu chuỗi văn bản.) Có vẻ như tất cả các triển khai tôi đã tìm thấy phân chia công việc bên trong hàm qsort, tạo ra một lượng lớn chi phí trong phân vùng số lượng công việc tương đối nhỏ cho mỗi luồng .quicksort song song trong c

Sẽ không nhanh hơn nhiều khi chia 1 triệu chuỗi cho số chuỗi (trong trường hợp của tôi, 24 luồng), và yêu cầu chúng hoạt động trên một phần, sau đó thực hiện hợp nhất? Cấp, điều này có những bất lợi về lý thuyết rằng nó không phải là một loại tại chỗ, nhưng với gobs của bộ nhớ có sẵn nó không phải là một vấn đề. Máy chạy trên có 12 lõi vật lý/24 logic rất nhanh và 192 GB (có, gigabyte) bộ nhớ. Hiện tại, ngay cả trên máy này, sắp xếp mất gần 8 phút!

+0

có thể. phụ thuộc. về vấn đề này. trên phần cứng. – Anycorn

+0

http://en.wikipedia.org/wiki/Quicksort#Parallelization –

+0

http://en.wikipedia.org/wiki/External_sorting –

Trả lời

8

có nó không thể nhanh hơn nhiều để chia 1 triệu chuỗi bằng của số đề (trong trường hợp của tôi, 24 bài), và có họ từng làm việc trên một phần, và sau đó làm một mergesort ?

Đó là một ý tưởng hay.

Nhưng bạn có thể thực hiện một số quan sát bằng cách viết chương trình đồ chơi cho quick-sortmerge-sort và tận dụng lợi thế của thuật toán/thời gian chạy-hành vi của chúng.

Ví dụ: quick-sort sắp xếp trong khi dividing quá trình (pivot phần tử sẽ được đặt ở vị trí cuối cùng ở cuối của lần lặp đó) và merge-sort sắp xếp trong khi merging (sắp xếp được thực hiện sau khi toàn bộ nhóm làm việc được chia nhỏ (chia) thành các đơn vị rất chi tiết có thể được so sánh trực tiếp với hạt-đơn vị khác (== hoặc strcmp()).

Trộn lên các thuật toán dựa vào bản chất của bộ lao động là một ý tưởng tốt.

liên quan đến việc phân loại song song với, đây là parallel merge-sort của tôi để bạn bắt đầu.

#include <stdio.h> 
#include <pthread.h> 
#include <stdlib.h> 

#define NOTHREADS 2 

/* 

gcc -ggdb -lpthread parallel-mergesort.c 


NOTE: 
The mergesort boils downs to this.. 
Given two sorted array's how do we merge this? 

We need a new array to hold the result of merging 
otherwise it is not possible to do it using array, 
so we may need a linked list 

*/ 

int a[] = {10, 8, 5, 2, 3, 6, 7, 1, 4, 9}; 

typedef struct node { 
int i; 
int j; 
} NODE; 

void merge(int i, int j) 
{ 
     int mid = (i+j)/2; 
     int ai = i; 
     int bi = mid+1; 

     int newa[j-i+1], newai = 0; 

     while(ai <= mid && bi <= j) { 
       if (a[ai] > a[bi]) 
         newa[newai++] = a[bi++]; 
       else      
         newa[newai++] = a[ai++]; 
     } 

     while(ai <= mid) { 
       newa[newai++] = a[ai++]; 
     } 

     while(bi <= j) { 
       newa[newai++] = a[bi++]; 
     } 

     for (ai = 0; ai < (j-i+1) ; ai++) 
       a[i+ai] = newa[ai]; 

} 

void * mergesort(void *a) 
{ 
       NODE *p = (NODE *)a; 
       NODE n1, n2; 
       int mid = (p->i+p->j)/2; 
       pthread_t tid1, tid2; 
       int ret; 

       n1.i = p->i; 
       n1.j = mid; 

       n2.i = mid+1; 
       n2.j = p->j; 

       if (p->i >= p->j) return; 

       ret = pthread_create(&tid1, NULL, mergesort, &n1); 
       if (ret) { 
         printf("%d %s - unable to create thread - ret - %d\n", __LINE__, __FUNCTION__, ret);  
         exit(1); 
       } 


       ret = pthread_create(&tid2, NULL, mergesort, &n2); 
       if (ret) { 
         printf("%d %s - unable to create thread - ret - %d\n", __LINE__, __FUNCTION__, ret);  
         exit(1); 
       } 

       pthread_join(tid1, NULL); 
       pthread_join(tid2, NULL); 

       merge(p->i, p->j); 
       pthread_exit(NULL); 
} 


int main() 
{ 
       int i; 
       NODE m; 
       m.i = 0; 
       m.j = 9; 
       pthread_t tid; 

       int ret; 

       ret=pthread_create(&tid, NULL, mergesort, &m); 
       if (ret) { 
         printf("%d %s - unable to create thread - ret - %d\n", __LINE__, __FUNCTION__, ret);  
         exit(1); 
       } 

       pthread_join(tid, NULL); 

       for (i = 0; i < 10; i++) 
           printf ("%d ", a[i]); 

       printf ("\n"); 

       // pthread_exit(NULL); 
       return 0; 
} 

Chúc bạn may mắn!

3

Quicksort liên quan đến việc vượt qua một danh sách ban đầu, danh sách này sắp xếp danh sách thành các phần cao hơn và thấp hơn trục xoay.

Tại sao không làm điều đó trong một chủ đề, và sau đó sinh ra một sợi khác và ủy quyền nó đến một nửa trong khi luồng còn lại chiếm nửa còn lại, v.v ...

1

Bạn đã cân nhắc sử dụng thuật toán sắp xếp được thiết kế đặc biệt để sắp xếp chuỗi không? Dường như nó có thể là một ý tưởng tốt hơn là cố gắng triển khai quicksort tùy chỉnh. Sự lựa chọn cụ thể của các thuật toán có thể phụ thuộc vào độ dài của các chuỗi và chúng khác nhau như thế nào nhưng một số radix sort có lẽ không phải là một cược xấu.

Nhanh chóng google search bật lên an article về sắp xếp chuỗi. Tôi đã không đọc nó nhưng Sedgewick và Bentley thực sự biết công cụ của họ. Theo tóm tắt, thuật toán của họ là một hỗn hợp của Quicksort và radix sắp xếp.

Một giải pháp có thể khác là bọc một thuật toán sắp xếp song song từ C++.Triển khai STL của GNU có một parallel mode, trong đó có triển khai thực hiện nhanh dọc. Đây có lẽ là giải pháp dễ nhất.

+0

Đó là một liên kết tuyệt vời. Dường như bản ngã họ sử dụng để phân loại các chuỗi có ít nhất 2x nhanh như qsort. Nhìn một chút lông để làm song song, vì vậy đó sẽ là một dự án tương lai. – PaeneInsula

0

Để thực hiện truy cập bộ nhớ khả thi nhanh chóng đa luồng cần được tối ưu hóa sao cho hầu hết công việc sắp xếp được thực hiện bên trong bộ đệm không chia sẻ (L1 & L2). Đặt cược của tôi là quicksort single-threaded sẽ nhanh hơn so với muli-threaded trừ khi bạn đang chuẩn bị để đưa vào số tiền phong phú của công việc.

Một cách tiếp cận để kiểm tra có thể là một chủ đề để sắp xếp nửa trên và cách khác để sắp xếp giá trị thấp hơn.

Đối với một thói quen phân loại thích nghi chuỗi đặc biệt, khái niệm có vẻ kỳ lạ đối với tôi. Tôi có nghĩa là không có nhiều trường hợp phân loại một vector chỉ chuỗi (hoặc số nguyên) là đặc biệt hữu ích. Thông thường, dữ liệu sẽ được sắp xếp trong một bảng với các cột và hàng và bạn sẽ muốn sắp xếp các hàng theo một cột chứa các chữ cái, và nếu chúng bằng nhau, bạn sẽ sắp xếp bằng cột bổ sung có chứa dấu thời gian hoặc xếp hạng hoặc cái gì khác. Vì vậy, thường trình sắp xếp có thể xử lý một bộ quy tắc sắp xếp đa cấp có thể chỉ định bất kỳ loại dữ liệu nào (boolean, integer, date, strings, floating point etc) theo bất kỳ hướng nào (tăng dần hoặc giảm dần) trong cột của bảng.