我接到了用OpenMP进行存储桶排序的任务,我决定对每个存储桶进行快速排序.该要求要求我通过不断增加整数数量和更改线程数量进行测试,直到16个线程达到100万个整数.

以下是我的C语言代码:

#include <stdio.h>
#include <omp.h>
#include <time.h>
#include <stdlib.h>
#include <math.h>

void swap(int* a, int* b) {
    int temp = *a;
    *a = *b;
    *b = temp;

}

int partition(int arr[], int low, int high) {

    int pivot = arr[high];
    int i = low - 1;

    for (int j = low; j < high; j++) {

        if (arr[j] <= pivot) {
            i++;
            swap(&arr[i], &arr[j]);
        }

    }

    swap(&arr[i + 1], &arr[high]);

    return (i + 1);
}

void quickSort(int arr[], int low, int high) {

    if (low < high) {
        int pi = partition(arr, low, high);

        quickSort(arr, low, pi - 1);
        quickSort(arr, pi + 1, high);
    }

}

int main(int argc, char* argv[]) {

    //Check arguments
    if (argc > 3 || argc < 3) {
        fprintf(stderr, "Error: Invalid arguments. This program require 2 arguments.\nUsage: ./bucketSort <thread number> <amount of random number>\n");
        return 1;
    }

    printf("Random seed");

    //Initialize random seed
    srand((unsigned)time(NULL));

    int threadNum = atoi(argv[1]);
    int randomTime = atoi(argv[2]);

    int* numArr = (int*)malloc(randomTime * sizeof(int));

    if(numArr == NULL){
        fprintf(stderr, "Error: Unable to allocate memory.");
        return 1;
    }

    printf("\nStart random");

    //Since RAND_MAX is limited to 0x7FFF (32,767), so we need to get creative to random beyond RAND_MAX
    for (int i = 0; i < randomTime; i++) {

        int rand1 = rand();
        int rand2 = rand();
        int rand3 = rand();

        int combinedRandom = ((rand1 % 100) * 1000) + ((rand2 % 100) * 10) + (rand3 % 10);

        numArr[i] = combinedRandom;

    }

    printf("\nFinished Random");

    double timeSpent = 0;

    int rangePerBucket = ceil(99999 / threadNum);

    int* outputArr = (int*)malloc(randomTime * sizeof(int));

    int* groupMemberCount = (int*)malloc(threadNum * sizeof(int));

    if(outputArr == NULL || groupMemberCount == NULL){
        fprintf(stderr, "Error: Unable to allocate memory.");
        return 1;
    }

    clock_t begin = clock();

    printf("\nStart parallel section.");

    #pragma omp parallel shared(numArr, outputArr, groupMemberCount) num_threads(threadNum)
    {

        int myID = omp_get_thread_num();
        int totalThread = omp_get_num_threads();

        int beginRange = myID * rangePerBucket;
        int endRange = (myID + 1) * rangePerBucket - 1;

        int* temp = (int*)omp_alloc(rangePerBucket * sizeof(int), omp_large_cap_mem_alloc);

        if( temp == NULL ){
            fprintf(stderr, "Error: Thread %d is unable to allocate memory.", myID);

        }

        int memberCount = 0;

        //Put in bucket
        for (int j = 0; j < randomTime; j++)
        {
            if (numArr[j] >= beginRange && numArr[j] <= endRange) {
                temp[memberCount] = numArr[j];
                memberCount++;
            }
        }

        groupMemberCount[myID] = memberCount;

        int* myGroup = (int*)omp_alloc(memberCount * sizeof(int), omp_large_cap_mem_alloc);

        if( myGroup == NULL ){
            fprintf(stderr, "Error: Thread %d is unable to allocate memory.", myID);
        }

        for (int i = 0; i < memberCount; i++) {
            myGroup[i] = temp[i];
        }

        //Sort
        quickSort(myGroup, 0, memberCount - 1);
        printf("\nThread %d of %d has finished sorting.", myID, totalThread);

        //Find the start of output array
        int startIndex = 0;
        for( int i = 0; i < myID; i++ ){
            startIndex += groupMemberCount[i];
        }

        //Combine array
        for (int k = 0; k < memberCount; k++) {

            outputArr[startIndex + k] = myGroup[k];

        }

        printf("\nArray from thread %d has combined.", myID);

        omp_free(myGroup, omp_large_cap_mem_alloc);
        omp_free(temp, omp_large_cap_mem_alloc);
    }

    free(numArr);
    free(outputArr);
    free(groupMemberCount);

    clock_t end = clock();

    timeSpent = (double)(end - begin) / CLOCKS_PER_SEC;

    printf("\nTime spent sorting: %f seconds.\n", timeSpent);

    return 0;
}

我用gcc -fopenmp ./bucketSort.c -o ./bucketSort把它编辑好了.在我开始测试gcc -fopenmp ./bucketSort.c -o ./bucketSortK整数之前,一切都运行得很好(我在主题中写了200K,因为我的程序分配了它两次).程序在打印Finished Random之后立即返回malloc(): corrupted top size(那么numArr中的第一个gcc -fopenmp ./bucketSort.c -o ./bucketSortK就可以了吗?)这是我第一次使用malloc()omp_alloc(),如果我做错了什么,请随时纠正我.我在Ubuntu WSL btw中运行这段代码.

我试过的是:

  • 我试了calloc(),但结果是一样的,在第二个calloc()之后出错.
  • 我试着把ulimit增加到unlimit.

推荐答案

通常,valgrind或-fsanitize=address可以很好地诊断此类错误.

编译并链接到-fsanitize=address显示此行上存在堆溢出:

                temp[memberCount] = numArr[j];

在这一点上,memberCount变量等于rangePerBucket.两者都比randomTime少1.但temp数组只有rangePerBucket个元素,因此该索引超出范围.

C++相关问答推荐

如何避免重新分配指针数组时,我们从一开始就不知道确切的大小

当main函数调用被重构时,C函数给出错误的结果

警告:C++中数组下标的类型为‘char’[-Wchar-subpts]

为什么内核使用扩展到前后相同的宏定义?

从纯C中访问通用项对话框

当输入负数时,排序算法存在问题

为什么我可以在GCC的标签后声明变量,但不能声明Clang?

tick.q中的Kdb+键控表语法

将回调/基于事件的C API转换为非回调API

循环中的静态变量与块中的变量和循环

当我用scanf(&Q;%S%S%S&Q;,单词0,单词1,单词2)输入多个单词时,除了最后一个单词外,每个单词的第一个字符都丢失了

用C++高效解析HTTP请求的方法

CS50 pset 5的皱眉脸正确地处理了大多数基本单词,并且拼写判断不区分大小写.

从整型转换为浮点型可能会改变其值.

将数组中的所有元素初始化为 struct 中的相同值

malloc 属性不带参数

变量的指针右对齐,函数的指针左对齐

C simd _m128 晶圆厂

仅使用其内存地址取消引用 C 中的 struct

我们可以在不违反标准的情况下向标准函数声明添加属性吗?