У меня проблема с буфером, не захватывает все суммы на моей программе C с потоками - PullRequest
0 голосов
/ 20 мая 2019

Итак, что-то не так с захватом данных из буфера. У меня есть несколько потоков производителей и один потребительский поток, но результат суммы данных, извлеченных из буфера, меньше, чем фактические вычисления

вот мой код полный код

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

    void *do_work(void *es) 


   {


.....

        while (1) {

.... 
                for (i = start; i < end ; i++) {
                    pthread_mutex_lock (&sum_mutex);
                    while(items_buffer==NTHREADS){
                            pthread_cond_wait(&produzir,&pc);
                        }
                        pthread_mutex_lock(&mutex_calculo1);
                        mysum= a[i]*a[i];
                        buffer[items_buffer]=mysum;
                        items_buffer++;
                        //printf("o meu buffer tem %d items a soma parcial é de %d e o buffer tem %d\n",items_buffer,mysum,buffer[items_buffer]);
                        pthread_mutex_unlock(&mutex_calculo1);
                        pthread_cond_signal(&consumir);
                        pthread_mutex_unlock (&sum_mutex);

                }
        }
        saidas=saidas+1;
        //printf("tarefa %d de saída\n",tids);
        pthread_exit(NULL);
        return NULL;
}

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

void *do_sum(void *ts) 
{
int i;
 pthread_mutex_lock(&mutex_geral);



    printf("Sou a thread somadora\n");
    pthread_cond_signal(&cond);

    pthread_mutex_unlock(&mutex_geral);

    while(items_buffer==0){
        pthread_cond_wait(&consumir,&pc);
    }

    while(saidas<NTHREADS){


        for(i=0;i<items_buffer;i++){
            pthread_mutex_lock(&mutex_soma);
            soma_buffer+=buffer[i];
            items_buffer--;
            //printf("o meu buffer ficou com %d items\n",items_buffer);
            pthread_mutex_unlock(&mutex_soma);
        }
        pthread_cond_signal(&produzir);
    }
    pthread_mutex_lock(&mutex_soma);
    for(i=0;i<items_buffer;i++){
            soma_buffer+=buffer[i];
            items_buffer--;
            //printf("o meu buffer ficou com %d items\n",items_buffer);
        }
        pthread_mutex_unlock(&mutex_soma);
    printf("Sou a thread somadora estou de saida\n");

    pthread_exit(NULL);
    return NULL;

}

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

вот мой код полный код

1 Ответ

2 голосов
/ 20 мая 2019

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

Edit: так что это не единственная проблема Здесь есть ряд проблем, я думаю, что вам, возможно, придется пересмотреть распараллеливание - Из того, что я могу сказать , из-за того, как вы используете переменную условия вместе со своим мьютексом, ваши потоки не работают одновременно. Вы блокируете все, выполняете сумму на одном блоке, разблокируете и затем возвращаетесь в очередь, чтобы дождаться следующего сигнала финиша. По сути, это последовательная операция с дополнительными издержками механизмов синхронизации.

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

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

Основная причина, по которой вы используете так много блокировок, - это использование статических переменных для буферов. Вам не нужно будет блокировать и очищать ваши буферы, если вы используете локальные переменные потока.

...