Как структурировать приложение на С++ для использования многоядерного процессора
Я создаю приложение, которое будет отслеживать некоторые объекты с помощью видеокамеры и использовать информацию из этого, чтобы запустить систему частиц в OpenGL. Код для обработки видеопотока несколько медленный, 200 - 300 миллисекунд за кадр прямо сейчас. Система, в которой он будет работать, имеет двухъядерный процессор. Чтобы максимизировать производительность, я хочу разгрузить материал обработки камеры на один процессор и просто передать соответствующие данные обратно в основное приложение по мере его доступности, оставив основное приложение на другом процессоре.
Что мне нужно сделать, чтобы разгрузить работу камеры другому процессору и как мне обрабатывать связь с основным приложением?
Изменить:
Я запускаю 64-разрядную версию Windows 7.
Ответы
Ответ 1
В принципе, вам нужно многопоточное приложение. Каждый поток исполнения может насыщать только одно ядро. Отдельные потоки, как правило, работают на отдельных ядрах. Если вы настаиваете на том, что каждый поток ALWAYS выполняется на конкретном ядре, то каждая операционная система имеет свой собственный способ определения этого (маски сродства и т.д.)... но я бы не рекомендовал его.
OpenMP велик, но он немного толстый в заднице, особенно при объединении с параллелизмом. YMMV. Он прост в использовании, но не совсем лучший вариант. Он также требует поддержки компилятора.
Если вы находитесь в Mac OS X 10.6 (Snow Leopard), вы можете использовать Grand Central Dispatch. Это интересно прочитать, даже если вы не используете его, так как его дизайн реализует некоторые лучшие практики. Он также не является оптимальным, но он лучше, чем OpenMP, хотя он также требует поддержки компилятора.
Если вы можете обернуть свою голову, разбив приложение на "задачи" или "задания", вы можете перетащить эти задания на столько каналов, сколько у вас есть. Подумайте о том, как вы обрабатываете свою обработку как атомные единицы работы. Если вы можете сегментировать его правильно, вы можете одновременно запускать обработку вашей камеры на обоих ядрах и на ваш основной поток.
Если связь минимизирована для каждой единицы работы, то ваша потребность в мьютексах и других фиксирующих примитивах будет сведена к минимуму. Курсовая зернистая резьба намного проще, чем мелкозернистая. И вы всегда можете использовать библиотеку или фреймворк для облегчения бремени. Рассмотрите Boost Thread library, если вы возьмете ручной подход. Он предоставляет переносные обертки и приятную абстракцию.
Ответ 2
Я бы рекомендовал против OpenMP, OpenMP больше для числовых кодов, а не для модели потребителя/производителя, которая, как вам кажется, имеет.
Я думаю, что вы можете сделать что-то простое, используя boost-потоки, чтобы создать рабочий поток, общий сегмент памяти (для обмена данными), а также некоторый механизм уведомления для ваших данных доступен (посмотрите на форсированные прерывания потока).
Я не знаю, какую обработку вы делаете, но вы можете взглянуть на блоки потоков Intel и встроенные примитивы Intel, у них есть несколько функций для обработки видео, которые могут быть более быстрыми (при условии, что они имеют вашу функциональность )
Ответ 3
Вам нужна какая-то структура для обработки многоядерных процессоров. OpenMP кажется довольно простым выбором.
Ответ 4
Это зависит от того, сколько ядер у вас есть. Если у вас есть только 2 ядра (процессор, процессоры, hyperthreads, вы знаете, что я имею в виду), то OpenMP не может дать такого огромного увеличения производительности, но поможет. Максимальный выигрыш, который вы можете получить, делит ваше время на количество процессоров, поэтому он по-прежнему будет принимать 100-150 мс за кадр.
Уравнение есть
параллельное время = (([общее время выполнения задачи] - [код, который нельзя распараллелить])/[номер процессора] + [код, который нельзя распараллелить]
В принципе, OpenMP сканирует при обработке параллельных циклов. Его довольно простой в использовании
#pragma omp parallel for
for (i = 0; i < N; i++)
a[i] = 2 * i;
и bang, ваш for распараллелен. Это не работает для каждого случая, не каждый алгоритм может быть распараллелен таким образом, но многие могут быть переписаны (взломаны), чтобы быть совместимыми. Ключевым принципом является Single Instruction, Multiple Data (SIMD), применяя один и тот же код свертки к нескольким пикселям, например.
Но просто применение этой рецептуры поваренной книги идет вразрез с правилами оптимизации.
1-Бенчмаркинг вашего кода
2-Найдите РЕАЛЬНЫЕ узкие места с "научными" доказательствами (цифрами) вместо того, чтобы просто угадать, где вы думаете, что есть узкое место
3-Если это действительно обработка циклов, то OpenMP для вас
Возможно, простые оптимизации вашего существующего кода могут дать лучшие результаты, кто знает?
Другой путь - запустить opengl в потоке и обработке данных в другом потоке. Это поможет много, если opengl или ваша система рендеринга частиц потребует много энергии, но помните, что потоковая передача может привести к другим узким местам синхронизации.
Ответ 5
Как и то, что сказал Pestilence, вам просто нужно, чтобы ваше приложение было многопоточным. Было упомянуто много фреймворков, таких как OpenMP, так что вот еще один:
Блоки Intel Thread Building
Я никогда раньше не использовал его, но я слышал об этом.
Надеюсь, это поможет!