Ошибки сегмента с помощью pthreads_mutex - PullRequest
1 голос
/ 01 марта 2011

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

    for (int i = first; i < last; i++)
    {
            get_id(particles[i], box_id);
            pthread_mutex_lock(&locks[box_id.x + box_no * box_id.y]);
            //cout << box_id.x << "," << box_id.y << "," << thread_id << "l" << endl;
            box[box_id.x][box_id.y].push_back(&particles[i]);
            //cout << box_id.x << box_id.y << endl;
            pthread_mutex_unlock(&locks[box_id.x + box_no * box_id.y]);
    }

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

- это глобально объявленный вектор <вектор <vector <частиц_т *>>> блок, который представляет разложение моего (квадратного) домена на блоки.

Когда цикл начинается, box [i] [j] .size () был установлен в ноль для всехi, j и цикл должен возвращать частицы обратно в коробчатую структуру (функция get_id выдает правильные результаты, я проверял)

Массив pthread_mutex_t lock объявлен как глобальный

pthread_mutex_t * locks,

и размер задается потоком 0, а блокировки инициализируются потоком 0 до создания других потоков:

locks = (pthread_mutex_t *) malloc( box_no*box_no * sizeof( pthread_mutex_t ) );

for (int i = 0; i < box_no*box_no; i++)
{
    pthread_mutex_init(&locks[i],NULL);
}

Есть ли у вас какие-либо представления о том, что?Т может вызвать это?Код также запускается, если число процессоров установлено в 1, и кажется, что чем больше процессоров я использую, тем раньше происходит ошибка сегмента (он прошел всю симуляцию один раз на двух процессорах, но это, похоже,исключение)

Спасибо

Ответы [ 2 ]

1 голос
/ 02 марта 2011

Это только обоснованное предположение, но оно основано на устранении проблемы, если вы используете одну блокировку для всех блоков: push_back должен выделить память, что он делает с помощью шаблона std::allocator. Я не думаю, что allocator гарантированно является поточно-ориентированным, и я не думаю, что он гарантированно будет разбит на разделы, по одному на каждый vector. (Базовый operator new является поточно-ориентированным, но allocator обычно делает трюки с нарезкой блоков для амортизации стоимости operator new.)

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

Другая вещь, которую я бы попробовал, - это использовать одну блокировку для всех блоков, что, как мы знаем, работает, но перемещать операции блокировки / разблокировки за пределы цикла for, чтобы каждый поток мог спрятать все свои элементы одновременно. На самом деле это может быть быстрее, чем то, что вы пытаетесь сделать - меньше взламывания блокировки.

0 голосов
/ 01 марта 2011

Правильно ли инициализированы векторы box и box[i]?Вы только говорите, что установлен самый внутренний набор векторов.В противном случае это выглядит так, как будто компонент box_id x или y неверен и работает с конца одного из ваших массивов.

На какой части вы видите сбой?

...