Почему этот код не работает постоянно? - PullRequest
0 голосов
/ 23 февраля 2012

Я пишу простейшую сито, используя эратосфены для занятий. У меня есть 8 потоков, каждый из которых отвечает за сегмент диапазона номеров [1, 2 ^ 32]. По какой-то причине иногда поток [0] в моем массиве потоков не попадает в функцию, к которой поток обращается при создании. Другие всегда (кажется) делают. Пожалуйста, дайте мне знать, что не так с этим кодом. Предупреждение, я только изучаю C ++, поэтому могут быть синтаксические ошибки и т. Д., Что, я полагаю, вызывает ошибку. Потратил часы на это и сузил его до потока [0], который не всегда попадает в функцию. Я изменил значения # define, чтобы было легче отлаживать. Ошибка происходит в любом случае. Пожалуйста, меня не слишком интересуют другие комментарии о том, как я могу улучшить программу. Это должно произойти в ближайшее время, поэтому я просто хочу, чтобы все работало как есть. Большое спасибо!

#include <iostream>
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <bitset>
#include <sys/time.h>
#include <sys/resource.h>
#include <sched.h>
#include <vector>
#include <math.h>

using namespace std;

#define NUM_OF_THREADS 8
#define TWO_TO_THIRTY_SECOND 1000000 //4294967296
#define SQRT_TWO_TO_THE_THIRTY_SECOND 1000 //65536
#define TWO_T0_THIRTY_SECOND_OVER_EIGHT 125000 //536870976

typedef struct {
    unsigned long composite_to_remove_index;
    int thread_index;
    unsigned long prime_number;
} thread_info_t;

bitset<TWO_T0_THIRTY_SECOND_OVER_EIGHT> bitmap[NUM_OF_THREADS];
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_t thread[NUM_OF_THREADS];


static void * threadFunc(void *arg)
{

    thread_info_t info = *(thread_info_t *)arg;

    bitmap[info.thread_index][info.composite_to_remove_index] = 1;
    info.composite_to_remove_index += info.prime_number;

    int index_to_remove = (int)info.composite_to_remove_index;

    for(; index_to_remove < TWO_T0_THIRTY_SECOND_OVER_EIGHT; index_to_remove += info.prime_number)
    {
        if(bitmap[info.thread_index][index_to_remove] == 0)
        {
            bitmap[info.thread_index][index_to_remove] = 1;
            if(info.thread_index == 0)
            {
                cout << "bit " << index_to_remove << ": " << bitmap[info.thread_index][index_to_remove] << "\n";
            }
        }
    }

    return NULL;
}

int main (int argc, char * argv[])
{   
    int thread_ret_val;
    vector<unsigned long long> prime_numbers;
    thread_info_t info; 

    for(unsigned long long i = 2; i < SQRT_TWO_TO_THE_THIRTY_SECOND; i++)
    {
        if(bitmap[0][i] == 0)
        {
            prime_numbers.push_back(i);
            info.prime_number = i;

            for(unsigned long j = 0; j < NUM_OF_THREADS; j++)
            {
                if(j == 0)
                    info.composite_to_remove_index = i*2;
                else
                    info.composite_to_remove_index = (((TWO_TO_THIRTY_SECOND/NUM_OF_THREADS)*j) % i);
                info.thread_index = (int)j;


                thread_ret_val = pthread_create(&thread[info.thread_index], NULL, threadFunc, (void*)&info);
                if(thread_ret_val != 0)
                {
                    cerr << "create thread error " << strerror(thread_ret_val) << "\n";
                }
            }

            for(int j = 0; j < NUM_OF_THREADS; j++)
            {
                pthread_join(thread[j], NULL);
            }
        }
    }

    return 1;
}

1 Ответ

1 голос
/ 23 февраля 2012
Структура

info, которая передается всем потокам, должна быть уникальной для каждого потока, но при этом она непреднамеренно и иногда разделяется между потоками. Проблема в том, что info не гарантируется неизменным между вызовом pthread_create и началом threadFunc. После вызова pthread_create вы меняете содержимое info на следующей итерации, и может случиться, что только тогда предыдущий поток фактически скопирует info в первую строку threadFunc.

Вы должны иметь std::vector информационных структур и каждый раз вызывать pthread_create с разными info.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...