LinuxForum.Fans
Тема

Subroutine speed

Автор: Peter 5 сообщений 1323 просмотров
#229389

Здравствуйте!

Возникла непонятная проблема - время работы подпрограммы зависит от способа
её вызова.
Она декодирует jpg, содержащийся в массиве и в другой массив записывает bmp,
это делается в цикле.

Если она находится в одном c-файле с тестовой вызывающей программой либо
вызывается из статически слинкованной библиотеки (libxxx.a), то выполняется
одинаково быстро, а если вызывается из libxxx.so, то работает на 35% дольше.
Конкретно 4.45ms и 6.03ms.

Если же я вызываю её из программы на Qt, для которой она и предназначена,
то работает существенно дольше. Программа получает jpg от видеокамеры и для
отдельной проверки я использовал одну из сохранённых картинок, картинка была
неподвижная, т.е. и рабочая программа и тестовая проверялись на одном и том же
изображении. В рабочей программе тоже цикл, время измерялось перед и сразу
после вызова подпрограммы.

В программе на Qt создаётся 4 объекта некоего класса для работы с видеокамерой,
из каждого из которых вызывается эта подпрограмма. Программа выполняется на
Intel Core 2 Quad, т.е. четырёхядерном процессоре.

Если подпрограмма вызывается из статически слинкованной библиотеки libxxx_cpp.a,
полученной отдельно от Qt вызовом g++, она выполнятся 6.0 - 6.2ms. В pro-файле
есть стрoки

text

CONFIG += static link_prl release
CONFIG += mmx sse sse2

т.е. ещё дольше, чем в программе на C при вызове из libxxx.so.

Если же я вставляю эту подпрограмму и всё, что ей надо, в саму программу на Qt,
в тот модуль, в котором она и вызывается, она выполняется ещё дольше -
7.0 - 7.2ms, а я думал, что будет быстрее.

Работа функций Qt, преобразующих полученный jpg в объект типа QImage,
занимает 5.6 - 6.3ms в зависимости от ядра.


Во всех случаях опции компилятора одни и те же при создании программ и библиотек.

1) Почему такая заметная разница при вызове из *.a и из *.so? Ладно бы несколько
процентов, а у меня 35.

2) Почему при вызове из программы на Qt подпрограмма работает намного дольше, чем
при вызове из тестовой программе на C?
В тестовой программе jpg содержался в unsigned char массиве, в программе на Qt
в QByteArray массиве, для доступа использовалась функция char* data() и
возвращаемое ею значение преобразовывалось к (unsigned char *).

3) Почему в программе на Qt при включении подпрограммы в сам проект, он состоит
из нескольких cpp-модулей, она выполняется дольше, чем при вызове из библиотеки?
Казалось бы, должно быть наоборот.

Если же создать только один объект, работающий с видеокамерой, то все
подпрограммы работают быстрее. Моя при вызове из библиотеки выполняется 4.95ms,
при включении в саму программу - 6.0ms, а функции Qt отрабатывают за 5.2ms.


И вообще что теперь делать и как жить дальше, если происходят такие вещи?

Пётр.

#229478
Peter написал:
И вообще что теперь делать и как жить дальше, если происходят такие вещи?

чем время замеряли? профилировщиком, или "по-детски" (таймер до, таймер после, а по середине код), или простым time'ом? если второе, то что в качестве таймера использовали? при замере функция вызывалась один раз или многократно?

ЗЫ: я так понял "таинственная библиотека" - это libjpeg?
ЗЗЫ: лучше писать код, чем большие абзацы...

#229503
Fat-Zer написал:
[quote=Peter]И вообще что теперь делать и как жить дальше, если происходят такие вещи?

чем время замеряли? профилировщиком, или "по-детски" (таймер до, таймер после, а по середине код), или простым time'ом? если второе, то что в качестве таймера использовали? при замере функция вызывалась один раз или многократно?

ЗЫ: я так понял "таинственная библиотека" - это libjpeg?
ЗЗЫ: лучше писать код, чем большие абзацы...[/quote]
Замерял командой

text

clock_t times(struct tms *buf);

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

text

g++ -Wall -O3 -mtune=generic -c -o libjpgpetr_cpp.a jpgpetr.cpp

при этом при компилировании Qt-программы линковщик выдаёт сообщение
[console]g++: language lib not reconized[/console]
Я пробовал строить эту же библиотеку и средствами Qt, но время выполнения
при этом точно было не меньше.

Функция вызывалась многократно, в тестовой программе 128 раз, а в рабочей -
сколько успеет за 60 секунд.
Разности времён суммировались и вычислялось среднее.

Последний эксперимент - функция qt работает 6.0ms, моя в рабочей программе
при вызове из libjpgpetr_cpp.a - 6.3ms, при встраивании её в c-модуль
Qt-программы - 7.6ms. Выводятся результаты для всех четырёх ядер и они могут
различаться на 10%.

Т.е. меня сейчас интересует методологический подход - что я делаю не так, если
в тестовой программе при вызове функции из статической библиотеки и при вызове
из программного модуля с тестовой программой результат одинаковый, а при вызове
из Qt-программы разный?
И почему при вызове из самой Qt-программы результат хуже и намного?
Почему результат так отличается при вызове функции из тестовой программы и при
вызове из Qt-програмы, если запущены все 4 потока? Ядер ведь тоже 4.

Пётр.

#229816

вроде всё верно... единственное, что можно попробовать замерять время так: http://linuxforum.ru/viewtopic.php?id=12292, но ИМХО это тоже самое.
ещё статическую библиотеку обычно собирают с помощью ar'а. если есть только один исходник, то это бессмысленно - просто подключаете объектник при линковке. делая расширение .a, вы вводите в заблуждение тех, кто это будет читать.

идей по поводу разности результатов - нет.

#229924

Благодарю за ответ, возможно, попробую ar, ранее я его использовал только для получения информации
о библиотеках. gcc с опцией "-fpic" строит *.so, без него - *.a
------------------------------------
У меня появился новый результат.

В 64-разрядной Ubuntu-10.4, в которую установлен бинарный 64-разрядный
дистрибутив Qt-4.8.0, всё гораздо лучше.

Во-первых, сама Qt-программа стала работать в полтора раза быстрее - jpg от
видеокамеры обрабатывает за 36ms, а в 32-разрядной Ubuntu-11.04 - 53-57ms,
на 1/3 быстрее.

Во-вторых, в ней моя подпрограмма при вызове из рабочей программы работает
одинаково при вызове как из статической библиотеки, так и при включении
в текст программы.

Однако по-прежнему она при вызове из рабочей программы работает дольше,
чем при вызове из тестовой - 45-48ms вместо 40 при вызове из тестовой
программы.
К тому же она ускорилась заметно меньше, чем рабочая программа -
в 32-разрядной системе на том же видеопотоке она работает 44-46ms,
а в 64-разрядной - 40ms, т.е. ускорение процентов на 10-15.

М.б., кто-нибудь посоветует хотя бы, что сделать для повышения ускорения
подпрограммы при переходе от 32-разрядной системе к 64-разрядной?
Какие тут возможны ухищрения?

Пётр.

Войдите или зарегистрируйтесь, чтобы ответить.