简体   繁体   English

使用 OpenMP 并行化选择排序

[英]Parallelize selection sort using OpenMP

I need to implement an algorithm for parallel selection sort using OpenMP, although I couldn't find much information either on SO or on the Internet in general.我需要使用 OpenMP 实现并行选择排序算法,尽管我在 SO 或 Internet 上找不到太多信息。

Here's my serial code:这是我的序列号:

void selectionsort(int* arr, int size)
{
    for (int i = size - 1; i > 0; --i)
    {
        int max = i;
        for (int j = i - 1; j >= 0; --j)
        {
            if (arr[j] > arr[max])
            {
                max = j;
            }
        }
        swap(arr[i], arr[max]);
    }
}

Does anybody know how to implement this type of sorting algorithm in parallel?有人知道如何并行实现这种类型的排序算法吗? At least in theory?至少在理论上?

Since the outer for can't be parallelized due to the constant changes in the array, we need to parallelize the inner for.由于数组不断变化,外层的for无法并行化,所以我们需要将内层的for并行化。

So we need to use the max reduction, but since we just don't need the maximum value we also need the index of this maximum value, we need to declare a new reduction (Only available in OpenMP 4.0) that receives a struct, here it is fully functional:所以我们需要使用最大缩减,但由于我们不需要最大值,我们还需要这个最大值的索引,我们需要声明一个接收结构的新缩减(仅在 OpenMP 4.0 中可用),在这里它功能齐全:

#include <stdio.h>
#include <omp.h>

struct Compare { int val; int index; };
#pragma omp declare reduction(maximum : struct Compare : omp_out = omp_in.val > omp_out.val ? omp_in : omp_out)

void selectionsort(int* arr, int size)
{
    for (int i = size - 1; i > 0; --i)
    {
        struct Compare max;
        max.val = arr[i];
        max.index = i;
        #pragma omp parallel for reduction(maximum:max)
        for (int j = i - 1; j >= 0; --j)
        {
            if (arr[j] > max.val)
            {
                max.val = arr[j];
                max.index = j;
            }
        }
        int tmp = arr[i];
        arr[i] = max.val;
        arr[max.index] = tmp;
    }
}

int main()
{
        int x[10] = {8,7,9,1,2,5,4,3,0,6};
        selectionsort(x, 10);

        for (int i = 0; i < 10; i++)
                printf("%d\n", x[i]);
        return 0;
}

The solution posted by Gabriel Garcia works only for arrays of natural numbers . Gabriel Garcia 发布的解决方案仅适用于自然数数组

If you use this array you get a wrong result:如果你使用这个数组,你会得到一个错误的结果:

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

The reduction declaration:减持声明:

#pragma omp declare reduction(maximum : struct Compare : omp_out = omp_in.val > omp_out.val ? omp_in : omp_out)

does not specify an initializer-clause and therefore at every iteration of the parallel loop the max.val and max.index are initialized to 0 even though we initialize them before the loop.没有指定初始化子句,因此在并行循环的每次迭代中, max.valmax.index都被初始化为 0,即使我们在循环之前对它们进行了初始化。

Refer to user defined reduction syntax for more information.有关详细信息,请参阅用户定义的缩减语法

The correct declaration should be:正确的声明应该是:

#pragma omp declare reduction(maximum : \
                              struct Compare : \
                              omp_out = omp_in.val > omp_out.val ? omp_in : omp_out) \
                              initializer(omp_priv=omp_orig)

You can also do a 'minimum' reduction in the same way if you prefer (obviously, changing the indexes and relationship symbols).如果您愿意,您也可以以相同的方式进行“最小”缩减(显然,更改索引和关系符号)。

Selection sort is far from optimal. 选择排序远非最佳。 You should use a formally efficient algorithm in serial (eg qsort), since it will almost certainly beat threaded selection sort for nontrivial usage. 您应该使用串行的正式高效算法(例如qsort),因为它几乎肯定会击败线程选择排序以进行重要的使用。

The comment that suggests merge sort is a good one. 建议合并排序的评论很好。

Threading selection sort as you've shown here is not hard, but since it's the wrong thing to do, I'm not going to demonstrate it. 你在这里展示的线程选择排序并不难,但由于这是错误的事情,我不会去展示它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM