Как я могу заблокировать потоки до тех пор, пока не будет найдено основное число, разблокировать его, а затем заставить их ждать до следующего простого числа?

Я пишу многопоточное решето Эратосфена, где мне приходится использовать pthreads. Я почти уверен, что это можно сделать с помощью мьютексов и cond_waits. Я создаю 4 потока в начале программы, а затем заставляю их ждать, пока Решето Эратосфена не найдет простое число. Затем я должен разблокировать потоки, чтобы они могли помечать каждую итерацию этого простого числа в битовом массиве. Затем они должны снова заблокировать и ждать следующего простого числа, пока алгоритм решета Эратосфена не исчерпает себя новыми числами.

Это код из моей многопоточной функции:

while(!doneFlag){
        printf("Thread wile loop\n");
        pthread_mutex_lock(&lock);
        pthread_cond_wait(&cond, &lock);

        startingPosition = (double)(maxNum/numThreads) * i;
        endingPosition = (double)(maxNum/numThreads) * (i+1)-1;
        if(i == numThreads-1){
            endingPosition = maxNum;
        } 
... Until the end of the function ... 
pthread_mutex_unlock(&lock);
}
return (void*)0;

doneFlag — это флаг, который я устанавливаю в 1, когда алгоритм решета Эратосфена завершает работу со всеми числами. Я надеялся, что цикл while с функцией cond_wait() заставит потоки ждать ввода (до тех пор, пока остается ввод данных)

Вот часть сита в функции main():

while(outerCounter < sqrt(maxNum)){
    //searching numbers above the current for prime numbers
    //printf("Sieve While\n");
    for(innerCounter = outerCounter+1; innerCounter <= maxNum; innerCounter++){
        //not composite
        //printf("Sieve for\n");
        if(composite[innerCounter] == 0){

            printf("Prime found: %d\n", innerCounter);
            pthread_mutex_lock(&lock);
            pthread_cond_broadcast(&cond);
            pthread_mutex_unlock(&lock);

            outerCounter = innerCounter;
            numPrimes++;

        }
    }
}
doneFlag = 1;

Каким-то образом составные числа не помечаются как составные (хотя пара помечена). Я предполагаю, что это как-то связано с состоянием гонки с функцией main(), как она продолжает находить больше простых чисел, пока потоки все еще работают в фоновом режиме, тем самым изменяя простое число, пока потоки все еще работают.

Как я могу это исправить? Правильно ли настроены мои блокировки/cond_wait? Мне очень трудно найти ресурсы для этого в Интернете.

Спасибо!

Изменить: я также хочу убедиться, что каждый из моих потоков может запускать функцию одновременно (функция - это то, что помечает элементы в массиве как составные). Может быть, мьютексы не являются хорошей идеей в моей функции потока, поскольку я хочу, чтобы они работали вместе? (Каждый поток занимает другой сегмент массива)


person FeralShadow    schedule 05.03.2013    source источник
comment
Один комментарий заключается в том, что вы используете один и тот же мьютекс для блокировки, но упомянули 4 потока, которые должны выполняться параллельно. Это можно сделать с помощью семафора-счетчика со значением 4. В противном случае одновременно может работать только один поток с максимальной скоростью.   -  person fkl    schedule 05.03.2013


Ответы (1)


Файязкл сказал это первым. Используйте счетный семафор вместо приглушенного. Ищите производителя/потребителя, потому что это проблема, которую вы решаете!

Итак, я не знаком с алгоритмом, который вы используете, но я попытался понять, чтобы немного помочь. Я предполагаю, что каждый новый прайм - это новая работа?

В любом случае, основной цикл нужен для создания автономных заданий, чтобы поток заданий мог извлекать новое задание из очереди заданий и иметь всю необходимую информацию. Если задание представляет собой просто новое простое число, добавьте новое простое число в очередь и опубликуйте семафор подсчета (помните, что очередь нуждается в синхронизации)

Потоки сначала будут ожидать на счетном семафоре. Когда семафор становится сигнальным, поток просыпается и получает задание, которое было помещено в очередь до того, как sem был сигнализирован. Затем поток обработает задание и опубликует результат.

Я думаю, ваша проблема в том, что у вас нет централизованного способа создания новых заданий с явными параметрами задания, так что два или более потока просыпаются и получают одно и то же задание, или ни один.

person c.fogelklou    schedule 05.03.2013
comment
Я не знал, что семафоры могут использоваться совместно потоками. Если я хочу, чтобы потоки выполнялись одновременно с использованием семафоров, нужно ли мне определять число потоков семафоров? - person FeralShadow; 06.03.2013
comment
Неа. Используйте один семафор и инициализируйте его количеством «произведенных» заданий. Каждый раз, когда потоку требуется новое задание, он уменьшает значение семафора на 1. Если заданий нет, этот поток переходит в спящий режим до тех пор, пока производитель задания не создаст новое задание. Процесс уменьшения/ожидания семафора является атомарным и блокирующим и всегда будет возвращаться с владением одним из заданий. (если он не возвращает код ошибки). - person c.fogelklou; 06.03.2013