Вопрос по multithreading, c, pthreads, posix – Есть ли способ повторно использовать pthreads?

4

У меня есть функция, которая вызывается миллионы раз, и работа, выполняемая этой функцией, является многопоточной. Вот функция:

void functionCalledSoManyTimes()
{
  for (int i = 0; i < NUM_OF_THREADS; i++)
  {
    pthread_create(&threads[i], &attr, thread_work_function, (void *)&thread_data[i]);
  }
  // wait
}

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

Хотя многопоточность алгоритма таким способом действительно улучшила производительность более чем на 20%, мое профилирование показывает, что повторяющиеся вызовы pthread_create вызывают значительные накладные расходы.

Мой вопрос: есть ли способ достичь моей цели без звонкаpthread_create каждый раз функция вызывается?

Problem Solved.

Спасибо, ребята, я очень ценю вашу помощь! Я написал решениеВот используя ваши советы.

Вам нужно посмотреть наthread pool концепция. Здесь у вас есть пул потоков, которые ждут работы. Вы планируете эту работу, скажем, в очереди, - на которой потоки заблокированы, и один поток заберет работу и выполнит ее. Это довольно распространенная концепция, и, если у вас есть такая возможность, извлеките эту функциональность из чего-то вроде APR (Apache Portable Runtime.) Nim

Ваш Ответ

2   ответа
3

зи между потоками (кольцевой буфер, например), чтобы передать данные для обработки.

2

ое хранилище для пула потоков, но что произойдет, еслиfunctionCalledSoManyTimes сам можно вызвать из нескольких потоков? Это не очень хороший дизайн.

Что бы я сделал, чтобы справиться с подобной ситуацией, это создать ключ локального хранилища сpthread_key_create по первому звонку (используяpthread_once) и сохраните там ваш пул потоковpthread_setspecific первый разfunctionCalledSoManyTimes вызывается в данной теме. Вы можете предоставить функцию деструктора дляpthread_key_create который будет вызван, когда поток существует, и эта функция может быть ответственна за сигнал рабочим потокам в пуле потоков прекратить себя (черезpthread_cancel или какой-то другой механизм).

Это также хорошее решение, но я подозреваю, что оно часто не применимо, особенно если вы хотите сохранить реализациюfunctionCalledSoManyTimes непрозрачный / инкапсулированный.
Иногда вы можете загрузить проблему наверх - требуется вызывающая сторонаfunctionCalledSoManyTimes передать пул потоков, который создан / уничтожен предоставляемыми вами функциями. Это легко изменить, если код вызывающего абонента выглядит следующим образомfor (int i = 0; i < SOMANY; ++i) functionCalledSoManyTimes();Это не просто, если функция вызывается из множества несвязанных сайтов, и легко, но бесполезно, если вы хотите скрыть тот факт, что она многопоточна от вызывающей стороны.
Согласовано. Я упоминаю об этом, потому что хочу исключить это, прежде чем вводить скрытое общее состояние, статическое или локальное для потока. Если я не могу это исключить, это бонус. Другая возможность состоит в том, чтобы сказать вызывающему абоненту, что то, что он создает и передает, являетсяManyTimesFunctionOptimizer, Это тайно содержит пул потоков, и ваша реализация функции инкапсулирована, за исключением того факта, что она может дополнительно использовать этот объект для повышения скорости. Содержит ли этот объект пул потоков или кэш напоминаний (или оба) непрозрачно для вызывающей стороны.

Похожие вопросы