- •Cортировка массива методом Хоара(«Быстрая» сортировка) – сравнение параллельной и последовательной реализации
- •Описание «быстрой» сортировки
- •Алгоритм сортировки
- •Cортировка массива методом Хоара(«Быстрая» сортировка) – сравнение параллельной и последовательной реализации
- •Описание «быстрой» сортировки
- •Алгоритм сортировки
Cортировка массива методом Хоара(«Быстрая» сортировка) – сравнение параллельной и последовательной реализации
01.10.2011
Как и для большинства алгоритмов сортировки, методика «быстрой» сортировки взята из повседневного опыта. Чтобы отсортировать большую стопку алфавитных карточек по именам, можно разбить ее на две меньшие стопки относительно какой-нибудь буквы, например K. Все имена, меньшие или равные K, идут в одну стопку, а остальные – в другую.
Данный алгоритм очень удачно подходит для распараллеливания. Меня заинтересовало, какой прирост к производительности будет, если использовать потоки.
Описание «быстрой» сортировки
Подробно о самой сортировке можно прочитать на том же rsdn. Тут коснусь пары основных моментов. Вообще, главное в данной сортировке, что после выбора опорного элемента, слева от него остаются все элементы меньше его, а справа большие. И далее происходит рекурсивный вызов функции сортировки для каждого подмассива. Идея в том, чтобы сортировку обеих частей провести в отдельных поток. Теоретически, в идеальном варианте, когда слева и справа одинаковое число элементов, создавая 2 потока на 2-х ядерном процессоре, скорость выполнения должна увеличиться на 100%.
Алгоритм сортировки
Реализация сортировки наивная, опорным элементом изначально всегда берётся серединный элемент массива. При ветвлении создание потоков для обеих веток не разумно, ибо затраты на создание потока под меньший подмассив превышают время выполнения сортировки подмассива. Можно улучшить алгоритм: создавать поток лишь для большего подмассива, а меньший обрабатывать в текущем потоке.
view sourceprint
01.DWORD __stdcall SortMasP (LPVOID p)
02.{
03.lpArrayParam Params = (lpArrayParam)p;
04.if (Params->left>=Params->right) return 0;
05.int left, right, supporting;
06.int temp;
07.int * mas;
08.
09.left=Params->left;
10.right=Params->right;
11.mas = Params->mas;
12.supporting=(((lpArrayParam)p)->left+((lpArrayParam)p)->right)/2;
13.
14.while(Params->left<Params->right)
15.{
16.while ((Params->left<supporting)&&(mas[Params->left]<=mas[supporting]))
17.Params->left++; // Сдвиг левой границы
18.while ((Params->right>supporting)&&(mas[Params->right]>=mas[supporting]))
19.Params->right--; // Сдвиг правой границы
20.// Обмен граничных элементов
21.Swap(&mas[Params->left],&mas[Params->right]);
22.// Обновление индекса опорного элемента
23.if (Params->left == supporting ) supporting = Params->right;
24.else if (Params->right == supporting ) supporting = Params->left;
25.}
26.lpArrayParam Params1 = new ArrayParam;
27.Params1->left=left;
28.Params1->right=supporting-1;
29.Params1->mas = mas;
30.
31.lpArrayParam Params2 = new ArrayParam;
32.Params2->left=supporting+1;
33.Params2->right=right;
34.Params2->mas = mas;
35.
36.if(TCount<pc)
37.{
38.
39.HANDLE thr;
40.InterlockedIncrement(&TCount);
41.
42.if(Params2->right-Params2->left<Params1->right-Params1->left)
43.{
44.thr = CreateThread(0,0,(LPTHREAD_START_ROUTINE)SortMasP, Params1,0,0);
45.SortMasP(Params2);
46.WaitForSingleObject(thr, INFINITE);
47.}
48.else
49.{
50.thr = CreateThread(0,0,(LPTHREAD_START_ROUTINE)SortMasP, Params2,0,0);
51.SortMasP(Params1);
52.WaitForSingleObject(thr, INFINITE);
53.}
54.
55.InterlockedDecrement(&TCount);
56.CloseHandle(thr);
57.
58.}
59.else
60.{
61.SortMasP(Params1);
62.SortMasP(Params2);
63.}
64.
65.delete Params2;
66.delete Params1;
67.return 0;
68.}
Ну, и дополнительные функции/переменные, используемые в методе.
view sourceprint
01.//обмен элементов
02.void Swap(int *a, int *b)
03.{
04.int temp = *a; *a=*b; *b=temp;
05.}
06.
07.DWORD GetProcessorCount()
08.{
09.SYSTEM_INFO si;
10.GetSystemInfo(&si);
11.return si.dwNumberOfProcessors;
12.
13.}
14.
15.DWORD pc=GetProcessorCount(); //число процессоров
16.
17.//структура для передачи параметров
18.typedef struct _ArrayParam
19.{
20.int left;
21.int right;
22.int * mas;
23.
24.} ArrayParam, *lpArrayParam;
25.
26.LONG TCount = 0; //количество созданных потоков