Как ускорить шейкерную сортировку с помощью omp?
Каким образом можно ускорить шейкерную сортировку большого массива (100k).
Обязательное условие: с помощью OMP.
В моём случае лучший(при этом правильный) результат показали 8 потоков.
Я только начинаю разбираться в omp, поэтому принимаются любые советы, идеи, предложения
#include <iostream>
#include <ctime>
#include <fstream>
#include <omp.h>
#include <time.h>
using namespace std;
#define N 100000
int main()
{
srand(time(0));
int A[N], left = 0, right = N - 1, i, n;
double start, end;
for (int j = 0; j < N; j++)
{
A[j] = rand() % 20 + 1;
}
#pragma omp parallel num_threads(8)
{
start = omp_get_wtime();
while (left < right)
{
for (int i = left; i < right; i++)
{
if (A[i] > A[i + 1])
swap(A[i], A[i + 1]);
}
right--;
for (int i = right; i > left; i--)
{
if (A[i - 1] > A[i])
swap(A[i], A[i - 1]);
}
left++;
}
end = omp_get_wtime();
}
for (int q = 0; q < N; q++)
printf("%d ", A[q]);
printf("\nWork took %f seconds\n", end - start);
}
// results:
// 10k in 0,45 sec
// 100k in 11 sec
Ответы (1 шт):
- исправьте алгоритм, так чтобы он отсекал уже отсортированные концы. Это обязательная часть шейкера. Сравните свой код с кодом wiki.
- выделите код в отдельную функцию, так чтобы можно было передать указатель + размер + шаг между элементами.
- параллельно сортируете отдельные выборки (каждый 8-й элемент, начиная с 0-го, с 1-го, ... ), запуская функцию из (п. 2).
- параллельно сортируете кусочки (1/8) массива.
- в главном потоке применяете сортировку ко всему массиву (не распараллеливая).
Ускорение, получится за счет того, что к финальному шагу (п.5) массив "в основном", отсортирован. т.е. предется сделать гораздо меньше swap-ов, а за счет (п.1) гораздо меньше циклов верхнего уровня.
Это, конечно, уже не шейкер, но хоть что-то, на него похожее. Правда, теряем стабильность, исходного алгоритма. Если обязательно сохранять стабильность, то исключите п.3 (потеряете в производительности).