Должен ли я переписать свои подпрограммы DSP на C / C ++ или я хорошо справляюсь с небезопасными указателями на C #? - PullRequest
4 голосов
/ 04 ноября 2008

В настоящее время я пишу приложение на C #, которое выполняет большую часть цифровой обработки сигналов, которая включает в себя множество мелких, точно настроенных операций с памятью. Я написал эти подпрограммы с использованием небезопасных указателей, и они, кажется, работают намного лучше, чем я думал. Однако я хочу, чтобы приложение было максимально быстрым.

Получу ли я какое-либо преимущество в производительности от переписывания этих подпрограмм на C или C ++ или я должен придерживаться небезопасных указателей? Я хотел бы знать, что небезопасные указатели приносят в таблицу с точки зрения производительности, по сравнению с C / C ++.

РЕДАКТИРОВАТЬ: Я не делаю ничего особенного внутри этих подпрограмм, просто обычные вещи DSP: кеширующие передачи данных из одного массива в другой с большим количеством умножений, сложений, сдвигов битов и т. Д. В пути. Я ожидаю, что подпрограммы C / C ++ будут выглядеть почти так же (если не идентично), как их аналоги в C #.

РЕДАКТИРОВАТЬ: Большое спасибо всем за все умные ответы. Что я узнал, так это то, что я не получу никакого значительного прироста производительности, просто сделав прямой порт, если не произойдет какая-либо оптимизация SSE. Предполагая, что все современные компиляторы C / C ++ могут воспользоваться этим, я с нетерпением жду возможности попробовать. Если кто-то заинтересован в результатах, просто дайте мне знать, и я опубликую их где-нибудь. (Хотя может занять некоторое время).

Ответы [ 13 ]

16 голосов
/ 29 января 2009

На самом деле я сделал в точности то, что вы просите, только в области обработки изображений. Я начал с C # небезопасных указателей, затем перешел на C ++ / CLI и теперь я все кодирую на C ++. На самом деле, оттуда я перешел с указателей в C ++ на инструкции процессора SSE, так что я прошел весь путь. Еще не достигли ассемблера, хотя я не знаю, нужно ли мне это, я видел статью о CodeProject, в которой показано, что SSE может работать так же быстро, как и встроенный ассемблер, я могу найти его, если вы этого хотите.

Когда я пошел дальше, мой алгоритм изменил скорость с 1,5-2 кадра в секунду в C # с небезопасными указателями до 40 кадров в секунду. C # и C ++ / CLI были определенно медленнее, чем C ++, даже с указателями, я не смог получить более 10 кадров в секунду с этими языками. Как только я переключился на C ++, я сразу получил примерно 15-20 кадров в секунду. Еще несколько хитрых изменений, и SSE увеличил до 40 кадров в секунду. Так что да, это стоит понизить, если вы хотите скорость в моем опыте. Наблюдается явный прирост производительности.

9 голосов
/ 04 ноября 2008

Еще один способ оптимизировать код DSP - сделать его кеш дружественным. Если у вас есть много фильтров, которые нужно применить к вашему сигналу, вы должны применить все фильтры к каждой точке, т. Е. Ваш самый внутренний цикл должен быть над фильтрами, а не над данными, например ::100100

for each n do t´[n] = h(g(f(t[n])))

Таким образом, вы будете намного меньше загружать кеш и, скорее всего, получите хороший прирост скорости.

6 голосов
/ 04 ноября 2008

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

Попытка создания «оптимального» кода с самого начала отвлечет вас от написания рабочего кода в первую очередь. Помните, что 80% вашей оптимизации повлияет только на 20% вашего кода, так как во многих случаях только 10% вашего кода отвечают за 90% вашего процессорного времени. (YMMV, в зависимости от типа приложения)

Когда я пытался оптимизировать использование альфа-смешивания в нашем графическом наборе инструментов, я пытался использовать SIMD «голым металлом» в первую очередь: встроенный ассемблер. Вскоре я обнаружил, что встроенные функции SIMD лучше, чем чистая сборка, поскольку компилятор может оптимизировать читаемый C ++ с помощью встроенных функций, переставляя отдельные коды операций и максимально используя различные процессорные модули в ЦП.

Не стоит недооценивать силу вашего компилятора!

4 голосов
/ 29 января 2009

Получу ли я какое-либо преимущество в производительности? от переписывания этих подпрограмм в C / C ++ или я должен придерживаться небезопасных указателей?

Теоретически это не имеет значения - идеальный компилятор оптимизирует код, будь то C или C ++, до наилучшего из возможных ассемблеров.

На практике, однако, C почти всегда быстрее, особенно для алгоритмов типа указателя - он настолько близок, насколько вы можете добраться до машинного кода без кодирования в ассемблере.

C ++ ничего не приносит в таблицу с точки зрения производительности - он построен как объектно-ориентированная версия C, с гораздо большими возможностями и простотой использования для программиста. Хотя в некоторых случаях оно будет работать лучше, потому что конкретное приложение получит выгоду с объектно-ориентированной точки зрения, оно не должно было работать лучше - оно должно было обеспечить другой уровень абстракции, чтобы программирование сложных приложений было проще. *

Так что нет, скорее всего вы не увидите увеличения производительности при переходе на C ++.

Однако для вас, вероятно, важнее выяснить, чем избегать тратить на это время - я думаю, что было бы целесообразно заняться портированием и анализом. Вполне возможно, что если у вашего процессора есть определенные инструкции по использованию C ++ или Java, и компилятор знает о них, он может воспользоваться возможностями, недоступными в C. Невероятно, но возможно.

Однако процессоры DSP - общеизвестно сложные звери, и чем ближе вы подходите к сборке, тем выше производительность, которую вы можете получить (т. Е. Чем больше настраивается ваш код вручную). C гораздо ближе к сборке, чем C ++.

-Adam

3 голосов
/ 29 января 2009

Сначала позвольте мне ответить на вопрос о «безопасных» и «небезопасных»: вы сказали в своем посте «Я хочу, чтобы приложение было максимально быстрым», а это значит, что вы не хотите связываться с «безопасным» или «управляемые» указатели (даже не упоминают сборку мусора).

Относительно вашего выбора языков: C / C ++ позволяет вам гораздо проще работать с базовыми данными без каких-либо накладных расходов, связанных с модными контейнерами, которые все используют в наши дни. Да, это приятно , когда вас обнимают контейнеры, которые препятствуют сегментированию ... но более высокий уровень абстракции связан с контейнерами RUINS ваша производительность.

На моей работе наш код должен работать быстро. Примером могут служить наши многофазные ресамплеры, работающие с указателями и маскирующими операциями и фильтрацией DSP с фиксированной запятой ... ни один из этих умных трюков действительно невозможен без контроля уровня памяти и манипуляций с битами ==>, поэтому я говорю придерживаться C / C ++.

Если вы действительно хотите быть умным, напишите весь свой код DSP на низком уровне C. А затем смешайте его с более безопасными контейнерами / управляемыми указателями ... когда он достигнет скорости, вам нужно снять учебные колеса ... они слишком сильно тормозят.

(К вашему сведению, что касается снятия учебных колес: вам нужно проверить свой дополнительный код C DSP в автономном режиме, чтобы убедиться, что их использование указателя хорошее ... з / у это вызовет ошибку.)

РЕДАКТИРОВАТЬ: стр. «seg faulting» - это ЛЮКС для всех вас, разработчиков ПК / x86. Когда вы пишете встроенный код ... ошибка сегмента означает, что ваш процессор войдет в wuides и будет восстановлен только при выключении питания;).

2 голосов
/ 29 января 2009

Чтобы узнать, как получить прирост производительности, полезно знать части кода, которые могут стать причиной узких мест.

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

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

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

Заключение: вы можете портировать небольшие части вашего приложения на C.

1 голос
/ 04 февраля 2009

Mono 2.2 теперь имеет поддержку SIMD , благодаря которой вы можете получить как лучший из управляемых кодов, так и скорость.

Возможно, вы также захотите взглянуть на Возможно ли использование SSE в c #?

1 голос
/ 03 февраля 2009

Если вы настаиваете на том, чтобы придерживаться своего ручного рулона, без ручной оптимизации в ассемблере или подобном, C # должен подойти. К сожалению, на этот вопрос можно ответить только экспериментально. Вы уже находитесь в неуправляемом пространстве указателей, поэтому мне кажется, что прямой порт на C ++ не будет видеть существенной разницы в скорости.

Я должен сказать, однако, что у меня недавно была похожая проблема, и мы закончили тем, что отказались от ручного рулона после попытки использования библиотеки Intel Integrated Performance Primitives . Улучшения производительности, которые мы видели, были очень впечатляющими.

1 голос
/ 03 февраля 2009

Вы действительно хотите, чтобы приложение было максимально быстрым или просто быстрым? Это говорит вам, что вы должны делать дальше.

1 голос
/ 02 февраля 2009

C # не поддерживает SSE (пока существует монопроект для операций SSE). Поэтому C / C ++ с SSE определенно будет быстрее.

Однако вы должны быть осторожны с переходами между управляемыми и нативными системами, поскольку они довольно дорогие. Оставайтесь как можно дольше в любом мире.

...