Почему я использовал `InterlockedIncrement` для увеличения критической переменной, но все равно получил неправильный ответ? - PullRequest
1 голос
/ 18 июня 2019

Я неправильно использовал функцию Win API InterlockedIncrement или C ++?

Я написал параллельную программу для поиска простых чисел от 1 до N, используя Win API. Я использовал InterlockedIncrement, но все еще получаю неправильные ответы. Вот мой код:

#include <iostream>
#include <windows.h>
#include <process.h>
#include <vector>
#include <ctime>
#include <cmath>

using namespace std;

typedef unsigned long long element_t;
typedef element_t count_t;

count_t count;

element_t N;

const int BATCH_SIZE = (1 << 20) - 1;

bool prime(element_t n) {
    if (n < 2) {
        return false;
    }
    for (element_t i = 2, end = (element_t) sqrt(n) + 1; i < end; i++) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

struct arg_list_t {
    element_t from;
    element_t to;

    arg_list_t(element_t f, element_t t)
        : from(f), to(t) { }
};

unsigned int WINAPI thread_func(void *params) {
    arg_list_t *arg_list = static_cast<arg_list_t *>(params);
    element_t from = arg_list->from, to = arg_list->to;
    for (element_t i = from; i < to; i++) {
        if (prime(i)) {
            InterlockedIncrement(&count);
        }
    }
    _endthreadex(0);
    return 0;
}

int main(void) {
    cout << "Enter the value of N: ";
    cin >> N;

    vector<arg_list_t> arg_lists;
    vector<HANDLE> handles;
    vector<unsigned int> thread_ids;

    cout << "Windows API" << endl;
    cout << "[INFO] Calculating ..." << endl;

    clock_t start = clock();
    element_t from = 2, to = min(N, from + BATCH_SIZE) + 1;
    while (from < N) {
        unsigned int thread_id;
        arg_lists.push_back({from, to});
        handles.push_back((HANDLE) _beginthreadex(
            NULL, 0, thread_func, (void *) &arg_lists.back(), 0, &thread_id));
        thread_ids.push_back(thread_id);
        from = to;
        to = min(N, from + BATCH_SIZE) + 1;
    }
    WaitForMultipleObjects(handles.size(), &handles[0], TRUE, INFINITE);
    clock_t end = clock();

    cout << "[INFO] Done! Total time: " 
         << static_cast<double>(end - start) / CLOCKS_PER_SEC 
         << " second(s)" << endl;
    cout << "There are " << count 
         << " prime(s) in the range [1, " << N << "]" << endl;

    return 0;
}

Например, если я установлю N на 10 000 000, последовательная программа выдаст (правильный) ответ 664579, но программа выше даст ответы, такие как 300386, 442219.

Компилятор: MinGW64, g ++ 8.1.0 (Должен ли я использовать MSVC для компиляции кода?)

...