C - огромное количество posix-потоков, выходящих из-под контроля и больше не создающих новых - PullRequest
0 голосов
/ 03 декабря 2009

У меня есть назначение в классе, которое требует от нас использовать потоки POSIX и создать n * (n-1) / 2 из них для обработки набора данных из n элементов.

Вы можете думать об этом как о классическом «рукопожатии» по вероятности.

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

Однако мой цикл создания всех потоков через некоторое время прекращает их создание.

Для кода ниже, я увижу вывод как:

making thread
thread start
thread done
made thread 1944
making thread
thread start
thread done
made thread 1945
making thread
thread start
thread done
made thread 1946
making thread

какое-то время, но потом я перестану видеть сообщения "начало потока" и "поток завершен" и буду видеть только сообщения "создание потока, создание потока".

Вот цикл, который создает потоки:

    int tCtr = 0;
    tArr = (pthread_t*)malloc(((numbers_read) * (numbers_read - 1)/2) * sizeof(pthread_t));
    for(i=0; i<numbers_read; i++){
        int j;
        for(j=i; j<numbers_read; j++){
            // n(n-1)/2
            if(i != j){
                printf("making thread\n");
                struct comparison_struct *data;
                data = (struct comparison_struct *)malloc(sizeof(struct comparison_struct));
                data->i_value = &numbers[i];
                data->j_value = &numbers[j];
                data->i_arr_entry = &wArr[i];
                data->j_arr_entry = &wArr[j];
                pthread_create(&tArr[tCtr], NULL, compare_thread, (void *)data);
                printf("made thread %d\n", tCtr);
                tCtr++;
            }
        }
    }
    for(i=0; i<tCtr; i++){
        pthread_join(tArr[i], NULL);
    }
    free(tArr);

а вот подпрограмма, содержащая код потока:

void *compare_thread(void *vData) {
    printf("thread start\n");
    struct comparison_struct *data;
    data = (struct comparison_struct *)vData;
    if(*data->i_value <= *data->j_value){
        *data->i_arr_entry = 0;
    } else {
        *data->j_arr_entry = 0;
    }
    free(vData);
    printf("thread done\n");
    return NULL;
}

У кого-нибудь есть идеи? Я новичок в pthreads и не могу понять это.

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

Ответы [ 2 ]

4 голосов
/ 03 декабря 2009

проверьте возвращаемое значение pthread_create, возможно, вы достигли предела ресурса.

 pthread_create() will fail if:

 [EAGAIN]           The system lacked the necessary resources to create
                    another thread, or the system-imposed limit on the
                    total number of threads in a process
                    [PTHREAD_THREADS_MAX] would be exceeded.

 [EINVAL]           The value specified by attr is invalid.

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

0 голосов
/ 03 декабря 2009

если я помещу вызов pthread_join сразу после pthread_create ... тогда он блокируется в каждом потоке ... на самом деле только 2 потока будут выполняться одновременно.

Альтернатива присоединению к потокам - просто создать их как отдельные. Создайте и инициализируйте pthread_attr_t,, установите его отдельно и передайте атрибут с вашим pthread_create вызовом.

pthread_attr_t  attr;
int             ret;

ret = pthread_attr_init(&attr);
if (ret)
   // error .........

ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

for (....)
{
    //........
    ret = pthread_create(&tArr[tCtr], &attr, compare_thread, (void *)data);
    //.......
}

ret = pthread_attr_destroy(&attr);

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

...