在大型数据集上使用时,多线程合并排序错过了对某些元素的排序?

时间:2016-05-13 05:18:32

标签: c multithreading floating-point mergesort bigdata

家庭作业

我正在将数据划分为更小的矩阵并使用线程来优化递归排序。我的函数完美地适用于小数据集,其中元素的数量不超过2000.但是一旦数据开始变大,我开始得到一些乱序的元素并且不会出现任何内存错误当运行地址sanitiser或valgrind时。我还没有弄清楚。我确实尝试将枢轴更改为具有偶数或奇数元素的模数的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;
}

2 个答案:

答案 0 :(得分:1)

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

std::wstring LongPathFromShortPath(const wchar_t* lpszShortPath) {

    // Prevent truncation to MAX_PATH characters
    std::wstring shortPath = L"\\\\?\\";
    shortPath += lpszShortPath;

    // Calculate required buffer size
    std::vector<wchar_t> buffer;
    DWORD requiredSize = ::GetLongPathNameW(shortPath.c_str(), buffer.data(), 0x0);
    if (requiredSize == 0x0) {
        throw std::runtime_error("GetLongPathNameW() failed.");
    }

    // Retrieve long path name
    buffer.resize(static_cast<size_type>(requiredSize));
    DWORD size = ::GetLongPathNameW(shortPath.c_str(), buffer.data(), 
                                    static_cast<DWORD>(buffer.size()));
    if (size == 0x0) {
        throw std::runtime_error("GetLongPathNameW() failed.");
    }

    // Construct final path name (not including the zero terminator)
    return std::wstring(buffer.data(), buffer.size()-1);
}

答案 1 :(得分:-3)

我认为你有竞争条件,因为我没有看到任何锁定。您必须保护共享数据免受来自多个线程的同时访问。