C 在大数据集上使用多线程合并排序时,是否会遗漏对某些元素的排序?

C 在大数据集上使用多线程合并排序时,是否会遗漏对某些元素的排序?,c,multithreading,floating-point,mergesort,bigdata,C,Multithreading,Floating Point,Mergesort,Bigdata,家庭作业练习 我将数据划分成更小的矩阵,并使用线程优化递归排序。我的函数在元素数不超过2000个的小数据集上运行得非常好。然而,一旦数据开始变得比这更大,我就开始使一些元素无序,并且在运行地址消除器或valgrind时不会出现任何内存错误。我还没弄明白。我确实尝试过改变pivot,使它有一个if语句,对于偶数或奇数的元素,它有一个模,对于偶数元素,它按n/2进行划分,对于奇数元素,它按(n+1)/2进行划分,但这仍然不起作用。有人能看到我错过了什么或只是给我一个提示吗 // struct use

家庭作业练习

我将数据划分成更小的矩阵,并使用线程优化递归排序。我的函数在元素数不超过2000个的小数据集上运行得非常好。然而,一旦数据开始变得比这更大,我就开始使一些元素无序,并且在运行地址消除器或valgrind时不会出现任何内存错误。我还没弄明白。我确实尝试过改变pivot,使它有一个if语句,对于偶数或奇数的元素,它有一个模,对于偶数元素,它按
n/2
进行划分,对于奇数元素,它按
(n+1)/2
进行划分,但这仍然不起作用。有人能看到我错过了什么或只是给我一个提示吗

// struct used for merge sort threads
typedef struct {
    float* m;
    size_t n;
} thread_arg;

/*
 * Merge matrices together
 */
void merge(float* main_matrix, float* left_matrix, int left_elements, float* right_matrix, int right_elements) {
    // left_matrix index
    int l = 0;
    // right_matrix index
    int r = 0;
    // main_matrix index
    int m = 0;

    while (l < left_elements && r < right_elements) {
        if (left_matrix[l] < right_matrix[r]) {
            main_matrix[m++] = left_matrix[l++];
        } else {
            main_matrix[m++] = right_matrix[r++];
        }
    }

    while (l < left_elements) {
        main_matrix[m++] = left_matrix[l++];
    }

    while (r < right_elements) {
        main_matrix[m++] = right_matrix[r++];
    }
}

/*
 * Threaded merge sort
 */
void* merge_sort(void* arg) {
    thread_arg* t_arg = (thread_arg*) arg;

    // base case
    if (t_arg->n < 2) {
        return NULL;
    }

    size_t pivot = (t_arg->n / 2);

    // left and right sub-matrices
    float* left_matrix = malloc(sizeof(float) * pivot);
    float* right_matrix = malloc(sizeof(float) * (t_arg->n - pivot));

    // fill left_matrix
    for (size_t i = 0; i < pivot; i++) {
        left_matrix[i] = t_arg->m[i];
    }

    // fill right_matrix
    for (size_t i = pivot; i < t_arg->n; i++) {
        right_matrix[(i - pivot)] = t_arg->m[i];
    }

    // create structs for recursive thread call
    thread_arg t_arg1 = (thread_arg) {
        .m = left_matrix,
        .n = pivot
    };
    thread_arg t_arg2 = (thread_arg) {
        .m = right_matrix,
        .n = (t_arg->n - pivot)
    };

    // create threads and send structs to sort recursively
    pthread_t thread1;
    pthread_t thread2;
    pthread_create(&thread1, NULL, merge_sort, &t_arg1);
    pthread_create(&thread2, NULL, merge_sort, &t_arg2);
    // join threads to retrieve sorted sub-matrices
    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    // Merge left_matrix and right_matrix into sorted matrix.
    merge(t_arg->m, left_matrix, pivot, right_matrix, (t_arg->n - pivot));

    // free left and right matrices
    free(left_matrix);
    free(right_matrix);

    return NULL;
}

/**
 * Returns sorted matrix.
 */
float* sort(float* matrix) {
    float* result = cloned(matrix);

    // structs for threaded merge sort
    thread_arg t_arg = (thread_arg) {
        .m = result,
        .n = g_elements
    };

    merge_sort(&t_arg);

    return result;
}
//用于合并排序线程的结构
类型定义结构{
浮动*m;
尺寸;
}线程参数;
/*
*合并矩阵
*/
无效合并(浮点*主矩阵、浮点*左矩阵、整数左元素、浮点*右元素、整数右元素){
//左矩阵索引
int l=0;
//右矩阵索引
int r=0;
//主矩阵索引
int m=0;
while(ln<2){
返回NULL;
}
大小轴=(参数->n/2);
//左右子矩阵
浮点*左矩阵=malloc(sizeof(浮点)*枢轴);
浮点*右矩阵=malloc(sizeof(float)*(t_arg->n-pivot));
//填充左矩阵
对于(大小i=0;im[i];
}
//填充右矩阵
对于(大小i=pivot;in;i++){
右_矩阵[(i-轴)]=t_arg->m[i];
}
//为递归线程调用创建结构
线程参数t线程参数1=(线程参数){
.m=左_矩阵,
.n=枢轴
};
线程参数t线程参数2=(线程参数){
.m=右矩阵,
.n=(t_arg->n-pivot)
};
//创建线程并发送结构以进行递归排序
pthread_t thread1;
pthread_t thread2;
pthread_create(&thread1,NULL,merge_sort,&t_arg1);
pthread_create(&thread2,NULL,merge_sort,&t_arg2);
//连接线程以检索已排序的子矩阵
pthread_join(thread1,NULL);
pthread_join(thread2,NULL);
//将左矩阵和右矩阵合并为排序矩阵。
合并(t_arg->m,左_矩阵,枢轴,右_矩阵,(t_arg->n-枢轴));
//自由左右矩阵
自由(左_矩阵);
自由(右_矩阵);
返回NULL;
}
/**
*返回排序后的矩阵。
*/
浮点*排序(浮点*矩阵){
浮点*结果=克隆(矩阵);
//线程合并排序的结构
线程参数t线程参数=(线程参数){
.m=结果,
.n=g_元素
};
合并排序(&t参数);
返回结果;
}

我认为您有竞争条件,因为我没有看到任何锁。您必须保护共享数据,防止多个线程同时访问。

我认为您存在争用情况,因为我没有看到任何锁。您必须保护共享数据,防止多个线程同时访问。

问题似乎不是检查pthread\u create是否失败。通过修改代码进行检查,您可以在使用所有线程的情况下执行无线程调用。下面是一些伪代码

// create threads and send structs to recursively sort
pthread_t thread1;
if (pthread_create(&thread1, NULL, merge_sort, &t_arg1) != 0 || t_arg->n_threads == MAX_THREADS) {
    merge_sort(&t_arg1);
} else {
    no. of threads++
}

merge_sort(&t_arg2);

pthread_join(thread1, NULL);
no. of threads--

问题似乎不是检查pthread_create是否失败。通过修改代码进行检查,您可以在使用所有线程的情况下执行无线程调用。下面是一些伪代码

// create threads and send structs to recursively sort
pthread_t thread1;
if (pthread_create(&thread1, NULL, merge_sort, &t_arg1) != 0 || t_arg->n_threads == MAX_THREADS) {
    merge_sort(&t_arg1);
} else {
    no. of threads++
}

merge_sort(&t_arg2);

pthread_join(thread1, NULL);
no. of threads--

线程在单独的数组中工作,父线程在两个子线程中的每一个子线程上等待完成线程在单独的数组中工作,父线程在两个子线程中的每一个子线程上等待完成还没有找到问题,但作为旁注:将它们称为矩阵而不是数组是令人困惑的。这就是问题吗?:
if(l_矩阵[l]
函数的参数是
left_矩阵
right_矩阵
l_矩阵
是一个全局变量,它解释了你不会得到一个复杂的错误?)仅供参考,不要每次递归都启动两个线程。启动两个线程,然后让父线程坐在那里等待这两个线程是没有意义的。相反,启动一个线程,然后让父线程执行第二个线程将执行的操作(只需调用递归)然后,等待启动的线程,然后进行合并。此外,不要重复超过机器的核心计数。如果你认为这不重要,考虑最深层的分区数(LeN=2)。在一个由2048个元素组成的矩阵中。是的,这是1024个活动线程。不起作用。限制它…并回答您关于哪里会出错的问题。您从不检查
pthread\u create
的结果,所以请参阅我之前关于限制线程深度的评论的最后一个主题。此外,以您所做的方式分配存储是一种浪费E.考虑顶级调用方分配相同大小的两个数组,并将它们传递给递归,一个作为源数组,另一个作为工作区。中间调用方不会分配任何东西,并将这些数组的范围传递给递归。无法找到问题,但作为旁瓣:混淆了,称之为Mordi。这就是问题所在吗?:
if(l_矩阵[l]
函数的参数是
左_矩阵
右_矩阵
(是
l_矩阵
一个全局变量,它解释了你没有