Используя pthreads, я получаю «Ошибка сегментации (ядро сброшено)» только в больших значениях - PullRequest
0 голосов
/ 15 мая 2019

Это программа для вычисления (квадратной) суммы массива с использованием потоков.Это работает нормально, если элементы массива имеют до 2.000.000, но после этого я получаю ошибку «Ошибка сегментации (ядро сброшено)».Может быть, потому, что я использую Ubuntu на виртуальной машине, и я выделил 4 ГБ оперативной памяти?

Спасибо за ваше время!

#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>

int part = 0;
int local_elements = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void* square_sum(void* arg);

int main()
{
    int threads, total_elements;
    int i;
    void *loc_sum = NULL;
    long long total_sum = 0;


    printf("Give the number of threads: ");
    scanf("%d", &threads);


    /*-----Fixed big size array-----*/
    total_elements = 2000000; // <--- If this value gets big I get that error
    local_elements = total_elements/threads;
    int element_array[total_elements];

    for (int i=0; i<total_elements; i++) {
        //Filling all the positions with 1s
        element_array[i] = 1;
    }

    //Creating the threads
    pthread_t newthread[threads];
    for (int i=0; i<threads; i++) {
        //The thread function gets the element array
        pthread_create(&newthread[i], NULL, square_sum, (void *)element_array);
    }


    //Waiting for each thread to finish and creating the total_sum
    for (int i=0; i<threads; i++) {
        pthread_join(newthread[i], (void*) &loc_sum);
        printf("Thread %d returned the local_sum: %d \n", i, (int)loc_sum);
        total_sum += (int)loc_sum;  
    }

    printf("\nThe total square sum of the array is: %lld\n", total_sum);

    return 0;
}


void* square_sum(void* arg) {

    intptr_t local_sum = 0;



    int *element_array = (int *) arg;

    //--- Start of critical section ---
    pthread_mutex_lock(&mutex);

    //Each thread computes its part
    int thread_part = part++;

    for (int i = thread_part*local_elements; i < (thread_part+1)*local_elements; i++) {
        local_sum += element_array[i] * element_array[i];
        //printf("Thread %d says -- element %d is: %d \n", thread_part, i, element_array[i]);

    }


    pthread_mutex_unlock(&mutex);
    //--- End of critical section ---


    return ((void*)local_sum);


}

Ответы [ 2 ]

1 голос
/ 15 мая 2019

Киран Бирадар прав. Я получаю правильные результаты с ulimit -s 80000 (я запустил с правами root для установки высокого ulimit) для этой взломанной версии вашей программы. В качестве альтернативы, выделение массива в куче или как статическое также должно избежать проблемы размера стека, как упомянуто другим комментатором.

#include <pthread.h>
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

int part = 0;
int local_elements = 0;

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void* square_sum(void* arg) {

    int* local_sum = (int*)malloc(sizeof(int));



    int *element_array = (int *) arg;

    //--- Start of critical section ---                                                                                                                                                                                                                                                    
    pthread_mutex_lock(&mutex);

    //Each thread computes its part                                                                                                                                                                                                                                                        
    int thread_part = part++;

    for (int i = thread_part*local_elements; i <
             (thread_part+1)*local_elements; i++) {
        *local_sum += element_array[i] * element_array[i];
        //printf("Thread %d says -- element %d is: %d \n", thread_part, i,                                                                                                                                                                                                                 
        //element_array[i]);                                                                                                                                                                                                                                                               
    }
    pthread_mutex_unlock(&mutex);
//--- End of critical section ---                                                                                                                                                                                                                                                          


    return local_sum;

}


int main()
{
    int threads, total_elements;
    int i;
    int* loc_sum;
    long long total_sum = 0;


    printf("Give the number of threads: ");
    scanf("%d", &threads);


    /*-----Fixed big size array-----*/
    total_elements = 2000000; // <--- If this value gets big I get that error                                                                                                                                                                                                              
    local_elements = total_elements/threads;
    int element_array[total_elements];

    for (int i=0; i<total_elements; i++) {
        //Filling all the positions with 1s                                                                                                                                                                                                                                                
        element_array[i] = 1;
    }

    //Creating the threads                                                                                                                                                                                                                                                                 
    pthread_t newthread[threads];
    for (int i=0; i<threads; i++) {
        //The thread function gets the element array                                                                                                                                                                                                                                       
        pthread_create(&newthread[i], NULL, square_sum, element_array);
    }


    //Waiting for each thread to finish and creating the total_sum                                                                                                                                                                                                                         
    for (int i=0; i<threads; i++) {
        pthread_join(newthread[i], (void**)&loc_sum);
        printf("Thread %d returned the local_sum: %d \n", i, *loc_sum);
        total_sum += *(int*)loc_sum;
        free(loc_sum);
        printf("loc_sum %d\n", *loc_sum);
    }

    printf("\nThe total square sum of the array is: %lld\n", total_sum);

    return 0;
}
0 голосов
/ 15 мая 2019

Ваша проблема в том, что

int element_array[total_elements];

слишком велик для размещения в стеке.Для 2.000.000 позиций требуется 8 МБ памяти, а размер стека по умолчанию для Linux составляет 8 МБ, что можно увидеть, запустив ulimit -s.Чтобы исправить это, вы можете использовать malloc, чтобы выделить его в куче, или использовать ключевое слово static, так как он выделит массив в сегменте .data, который обычно имеет ограничение 4 Гб на машинах amd64.

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