C ++ проектирование многопоточного класса из непоточного класса
-
20-09-2019 - |
Вопрос
Я работаю над библиотекой, занимающейся кодированием / декодированием звука.Кодер должен быть способен использовать несколько ядер (т.е.несколько потоков, использующих библиотеку boost), если таковая имеется.То, что у меня есть прямо сейчас, - это класс, который выполняет все операции, связанные с кодированием.
Следующий шаг, который я хочу предпринять, - это сделать этот класс потоковым.Поэтому мне интересно, как это сделать.
Я думал о написании класса потоков, создании n потоков для n ядер, а затем вызове кодировщика с соответствующими аргументами.Но, возможно, это излишество и нет необходимости в другом классе, поэтому я собираюсь использовать "пользовательский интерфейс" для создания потоков.
Я надеюсь, что есть какие-нибудь предложения.
Редактировать: Я вынужден использовать несколько потоков для предварительной обработки, создавая статистику входных данных с помощью CUDA.Итак, если в системе есть несколько карт, единственный способ использовать их параллельно - это создать несколько потоков.
Пример: 4 Файла, 4 другой единицы вычисления (отдельные запоминающие устройства, уникальный идентификатор устройства).Каждый из файлов должен быть выполнен на одной вычислительной единице.
То, что у меня есть прямо сейчас, это:
class Encoder {
[...]
public:
worker(T data, int devId);
[...]
}
Поэтому я думаю, что лучший способ - вызвать worker из threaded из main()
boost::thread w1(&Encoder::worker, data0, 0);
boost::thread w2(&Encoder::worker, data1, 1);
boost::thread w3(&Encoder::worker, data2, 2);
boost::thread w4(&Encoder::worker, data3, 3);
и не для того, чтобы реализовать thread-класс.
Решение
Я думаю, что проблема больше на уровне дизайна, не могли бы вы немного подробнее рассказать о том, какие классы у вас есть?Я тоже работаю на CUDA, и обычно создается интерфейс (он же шаблон фасада) для использования уровня, специфичного для архитектуры (CUDA).
Редактировать:После прочтения интерфейса обновления я думаю, что вы поступаете правильно.Сохраните логику кодировщика внутри класса и используйте простой boost::threads для выполнения различных единиц работы.Просто обратите внимание на потокобезопасность внутри методов Encoder.
Другие советы
Взгляните на OpenMP ( Открытый ), если ваш компилятор поддерживает это.Это может быть так же просто, как добавить флаг компилятора и распылить на несколько #pragma
s.
Ваше текущее предложение работает только в том случае, если Encoder::worker
является static
.Я предполагаю, что это так.Одна из проблем заключалась бы в том, поддерживает ли ваша текущая реализация способ изящно прервать задание кодирования.Я полагаю, что в вашем коде формы есть какой-то метод:
while( MoreInputSamples ) {
// Do more encoding
}
Это может быть изменено с помощью некоторого дополнительного условия, которое проверяет, получил ли jobs сигнал прерывания.Я много работаю над декодированием видео, и мне нравится, чтобы мои классы декодирования были такими:
class Decoder {
public:
void DoOneStepOfDecoding( AccessUnit & Input );
}
Выходные данные обычно поступают в некоторый кольцевой буфер.Таким образом, я могу легко применить это как к однопоточным, так и к многопоточным сценариям.
Предыдущий код
boost::thread w1(&Encoder::worker, data0, 0);
недопустимо до тех пор, пока worker не станет статичным.
Есть Повышение.Задача по расписанию проверки, которое позволяет вам асинхронно вызывать любой вызываемый объект, следующим образом
boost::tasks::async(
boost::tasks::make_task( &Encoder::worker, data0, 0) ) );
Это приводит к тому, что Encoder::worker был вызван в пуле потоков по умолчанию.Функция возвращает дескриптор, который позволяет узнать, когда задача была выполнена.