C ++ проектирование многопоточного класса из непоточного класса

StackOverflow https://stackoverflow.com/questions/2446236

Вопрос

Я работаю над библиотекой, занимающейся кодированием / декодированием звука.Кодер должен быть способен использовать несколько ядер (т.е.несколько потоков, использующих библиотеку 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 ( Открытый ), если ваш компилятор поддерживает это.Это может быть так же просто, как добавить флаг компилятора и распылить на несколько #pragmas.

Ваше текущее предложение работает только в том случае, если 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 был вызван в пуле потоков по умолчанию.Функция возвращает дескриптор, который позволяет узнать, когда задача была выполнена.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top