вторник, 2 февраля 2010 г.

§ 4. LabVIEW против С или гонка за лидером

Здравствуйте, коллеги!

Сегодня ещё несколько слов о быстродействии LabVIEW программ. В предыдущем параграфе было показано то, что генерируемый LabVIEW код довольно "рыхлый". Как это отражается на быстродействии и есть ли резервы? Давайте разберёмся.

В качестве простенького примера займёмся вычислением центра масс восьмибитной картинки. (если вы забыли, что такое центр масс или центроид, то загляните в Википедию: Centroid, Center of Mass) Для теста возьмём картинку Лены в четверть мегапиксела. В качестве референсного примера я воспользуюсь IMAQ Centroid из библиотеки IMAQ Vision:


Этот пример даст мне значение центра масс в точке (265.19, 247.43):



Классическая схема вычисления примерно такая:

Заметьте, что использование типа I64 в данном случае более чем оправдано, иначе возникнет переполнение.

Сколько времени займёт вычисление? Приготовим простенький бенчмарк:



На моём компьютере получается 8 миллисекунд. Неплохо.

Пример хорош тем, что даёт богатую пищу для размышлений. Что произойдёт, если перейти от целочисленого типа к DBL? Давайте проверим:



Получилось 5.5 миллисекунд. Уже лучше.

Немного потеряв в точности, можно перейти к типу SGL:


Теперь 3,75 миллисекунды.

Хороший программист сразу предложит вариант улучшения, позволяющий избавиться от вложенного цикла, например такой:



Теперь получилось 3,25 миллисекунды. Что ж, на этом, пожалуй, остановимся. Строго говоря, можно попытаться совсем избавиться от арифметики с плавающей точкой и перейти к целочисленному типу, оставаясь при этом в рамках 32 бит, но это вызовет значительное усложнение кода (а выигрыш будет невелик).

Давайте кардинально изменим подход и перепишем этот участок кода на чистом Си. К вопросу подойдём "в лоб", взяв за основу самый первый пример:


Это замечательное упражнение также помогает попрактиковаться в передаче массива и кластера в DLL:


Технически я пользуюсь средой CVI, на которую навешан Интеловский компилятор.

Что же получается?



0,84 миллисекунды! Наш код работает вчетверо быстрее аналогичного LabVIEW кода, что и требовалось доказать. (Пытливый читатель может сравнить ассемблерные листинги обоих примеров).

Достигли ли мы предела производительности? Конечно нет, ведь можно использовать факт наличия двух или более ядер (наш код пока что однопоточный), или использовать SIMD комманды. Однако несмотря на очевидный выигрыш, конечно, не стоит бросаться и тут же переписывать куски кода на Си. Отлаживать такой код на порядок сложнее, да и при современном быстродействии компьютеров как правило в этом нет нужды. Рассматривайте эту возможность как резерв, который всегда есть, и который можно и нужно использовать при необходимости. А «ранняя оптимизация» — она, как правило, вредна и порой приводит к неоправданному увеличению сложности. Сначала закончите и отладьте функциональность кода, затем определите «узкие места», попытайтесь оптимизировать LabVIEW код, и лишь потом используйте «тяжёлую артиллерию».

До следующих встреч,

Андрей.

CentroidLVvsC.zip (5MB)

Комментариев нет:

Отправить комментарий