Выбор метода вызова процедур

Модераторы: DCV, Dimmy, victorst, kos, Prof1983

Выбор метода вызова процедур

Сообщение Prof1983 » Вс май 29, 2011 8:11:41

Задался вопросом какой метод вызова выбрать для функций внешних и внутренних модулей (fastcall, cdecl, stdcall, pascal, safecall)?
Для этого написал небольшую тестовую программку (TestCall).

http://aikernel.org/files/TestCall.zip - Тестирование скорости работы разных методов вызова функций внутри программы

На картинке в приложении отображается кол-во тиков затраченное на вызов тестируемой фукции COUNT_I раз.
COUNT_I = 100000000;
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Новый проект AiKernel
Аватара пользователя
Prof1983
Серьёзный посетитель
 
Сообщения: 206
Зарегистрирован: Ср окт 11, 2006 13:29:31
Откуда: Новосибирск

Re: Выбор метода вызова процедур

Сообщение Prof1983 » Вс май 29, 2011 9:39:01

Решил немного улучшить программу. Добавил вывод процентного значения времени которое требуется для вызова COUNT_I раз функций. За 100% принял самый быстрый вызов (fascall/register), остальные высчитываются как
= (<Текущее значение Ticks> * 100) div <Значение Ticks самого быстрого (fastcall)>
Получил очень странные странные цифры.
Подумал, что это может происходить из-за того, что при первом вызове происходит заполнение кеша процессора первого уровня. И дальнейшие выполняются из-за этого быстрее. Поэтому добавил первый расчет, который далее не используется. Но результаты тестирования не изменились.

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

В общем результаты на картинках. Сравните с тем, что было ранее (выше).
Прежнюю версию программы можно скачать здесь: http://aikernel.org/files/TestCall-0.2.0.zip
Текущую версию программы можно скачать здесь: http://aikernel.org/files/TestCall-0.2.1.zip
Самую последнюю версию программы можно скачать здесь: http://aikernel.org/files/TestCall.zip
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Новый проект AiKernel
Аватара пользователя
Prof1983
Серьёзный посетитель
 
Сообщения: 206
Зарегистрирован: Ср окт 11, 2006 13:29:31
Откуда: Новосибирск

Re: Выбор метода вызова процедур

Сообщение Prof1983 » Вс май 29, 2011 10:02:31

Нашел в чем проблема.
Оказывается, что если выполнять
Код: Выделить всё
ProcShortFastcallTicks := TestProcShortFastcall();
ShortFastcallLabel.Caption := IntToStr(ProcShortFastcallTicks);
то кол-во тиков у меня около 1600.
А если выполнять
Код: Выделить всё
ProcShortFastcallTicks := TestProcShortFastcall();
S := IntToStr(ProcShortFastcallTicks);
ShortFastcallLabel.Caption := S;
то кол-во тиков у меня на компьютере около 2570.
Здесь S-String; I-Integer.

Хотя подсчет кол-ва тиков находится внутри TestProcShortFastcall() и не должен зависеть от вызывающей процедуры.
Код: Выделить всё
function TestProcShortFastcall: Integer;
var
  I: Integer;
  T1: DWORD;
  T2: DWORD;
begin
  T1 := GetTickCount();
  for I := 0 to COUNT_I do
    ProcFastcall(1, 2);
  T2 := GetTickCount();
  Result := T2 - T1;
end;

В общем так можно разбираться долго. Я пришел к выводу, что вопрос метода вызова функций между модулями не сильно важен. Внутри модуля можно реализовать любой вызов, хоть все процедуры внутри модуля на чистом asm писать. Поэтому я выбираю метод вызова для всех межмодульных вызовов как stdcall. Тем более, что аналогичное решение существует в API MS Windows.

Кроме этого я встречал описание и сравнение cdecl (Linux) и stdcall, где stdcall был более производителен. К сожалению сейчас ссылки под руками на это сравнение у меня нет.
Новый проект AiKernel
Аватара пользователя
Prof1983
Серьёзный посетитель
 
Сообщения: 206
Зарегистрирован: Ср окт 11, 2006 13:29:31
Откуда: Новосибирск

Re: Выбор метода вызова процедур

Сообщение daner » Вс май 29, 2011 15:44:57

Поэтому я выбираю метод вызова для всех межмодульных вызовов как stdcall

заранее создаете проблемы* с портированием на платформы отличные от win32.

----------------
* проблемы конечно решаемые.
Аватара пользователя
daner
Эксперт ИИ
 
Сообщения: 1811
Зарегистрирован: Сб фев 10, 2007 19:10:44
Откуда: Israel

Re: Выбор метода вызова процедур

Сообщение Prof1983 » Вс май 29, 2011 16:10:11

daner писал(а):заранее создаете проблемы* с портированием на платформы отличные от win32.
У меня не так много опыта, чтобы предусмотреть на данном этапе возможные проблемы. Но вроде на *nix платформах __stdcall поддерживается не хуже других?
Какие могут возникать проблемы при портировании?
Новый проект AiKernel
Аватара пользователя
Prof1983
Серьёзный посетитель
 
Сообщения: 206
Зарегистрирован: Ср окт 11, 2006 13:29:31
Откуда: Новосибирск

Re: Выбор метода вызова процедур

Сообщение daner » Вс май 29, 2011 22:31:54

на сколько я знаю, не поддерживаются. обычно просто создаются пустые дефайны (ну типа __stdcall). Т.е. де-факто все равно происходят cdecl вызовы. Хотя, может народ как-то и изголяется на что-то другое.
Аватара пользователя
daner
Эксперт ИИ
 
Сообщения: 1811
Зарегистрирован: Сб фев 10, 2007 19:10:44
Откуда: Israel

Re: Выбор метода вызова процедур

Сообщение Василий » Пн май 30, 2011 0:31:46

Любопытно что такие слова знают за рубежом. Изгаляться может быть. Вряд ли имеется в виду "голый".
Ищу лучшей жизни
Василий
Главный по тарелочкам
 
Сообщения: 1206
Зарегистрирован: Ср фев 07, 2007 12:22:27
Откуда: Санкт-Петербург

Re: Выбор метода вызова процедур

Сообщение Prof1983 » Пн май 30, 2011 3:36:46

daner писал(а):на сколько я знаю, не поддерживаются. обычно просто создаются пустые дефайны (ну типа __stdcall). Т.е. де-факто все равно происходят cdecl вызовы. Хотя, может народ как-то и изголяется на что-то другое.
Не понимаю. Почему (в компиляторах) в *nix нет реализации __stdcall? Вызов stdcall, на сколько я знаю, - это просто последовательная передача параметров через стек. Отличается от cdecl только тем, что в cdecl дополнительно передается кол-во передаваемых параметров.
Вообще мне известны такие типы передачи параметров: register, cdecl. stdcall, pascal, safecall.
Отличие pascal от stdcall только в направлении передачи параметров (справа на лево или наоборот).
safecall - это защищенный вызов (с фукцией-оберткой, которая отлавливает исключительные ситуации).

Так почему (в компиляторах) в *nix нет реализации __stdcall? Хотелось бы увидеть ссылку на источник (можно в личку).
Новый проект AiKernel
Аватара пользователя
Prof1983
Серьёзный посетитель
 
Сообщения: 206
Зарегистрирован: Ср окт 11, 2006 13:29:31
Откуда: Новосибирск

Re: Выбор метода вызова процедур

Сообщение daner » Пн май 30, 2011 15:02:26

Василий писал(а):Любопытно что такие слова знают за рубежом. Изгаляться может быть. Вряд ли имеется в виду "голый".

спасибо, что удостоили мою ошибку таким пристальным вниманием :)
Аватара пользователя
daner
Эксперт ИИ
 
Сообщения: 1811
Зарегистрирован: Сб фев 10, 2007 19:10:44
Откуда: Israel

Re: Выбор метода вызова процедур

Сообщение Prof1983 » Ср июн 01, 2011 8:54:26

Daner, так почему все-таки с вызовом stdcall не в Win32 могут быть проблемы?
Новый проект AiKernel
Аватара пользователя
Prof1983
Серьёзный посетитель
 
Сообщения: 206
Зарегистрирован: Ср окт 11, 2006 13:29:31
Откуда: Новосибирск

Re: Выбор метода вызова процедур

Сообщение Prof1983 » Ср июн 01, 2011 8:59:18

Сегодня протестировал скорость вызова разными методами (cdecl, stdcall, safecall, register) более сложную функцию и пришел к выводу, что различий по времени нет. Разница составляет несколько процентов, что я считаю не существенным. Поэтому для внешних (экспортируемых) функций модуля принимаю метод вызова stdcall. А внутри модулей можно реализовать как будет удобнее.
Новый проект AiKernel
Аватара пользователя
Prof1983
Серьёзный посетитель
 
Сообщения: 206
Зарегистрирован: Ср окт 11, 2006 13:29:31
Откуда: Новосибирск

Re: Выбор метода вызова процедур

Сообщение daner » Ср июн 01, 2011 17:29:41

Prof1983 писал(а):Daner, так почему все-таки с вызовом stdcall не в Win32 могут быть проблемы?

я не знаю. если честно меня этот вопрос вообще никогда не интересовал. я просто знаю, что в gcc это дело не используется, а он все-таки основной компилятор в Linux (это конечно не все *nix платформы но многие, да и на других его тоже используют не слабо).
хотя я 100% не буду утверждать, что gcc вообще никак это дело не поддерживает... что-то такое на поддержку stdcall похожее я видел в gcc к MinGW, но пустышка это там или нет, не знаю. На сколько я почитал про stdcall, его вообще придумали for windows и развивали только в нем. Зачем это сделали, остается для загадкой (в то время C уже во всю применял cdecl, а паскал свои вызовы, и какой смысл в перемене мес стека для паскалевского вызова, я так и не понял).
Аватара пользователя
daner
Эксперт ИИ
 
Сообщения: 1811
Зарегистрирован: Сб фев 10, 2007 19:10:44
Откуда: Israel

Re: Выбор метода вызова процедур

Сообщение Prof1983 » Ср июн 01, 2011 19:31:22

daner писал(а):про stdcall, его вообще придумали for windows и развивали только в нем
В общем-то у меня тоже такое впечатление сложилось. Я нигде не встречал stdcall в исходниках Unix программ. Хотя читал перевод интервью разработчика одного из ядер (не помню точно толи Linux, то ли Minix). Так вот там был примерно такой вопрос: "Планируете ли вы переходить на stdcall, вместо cdecl". С таким обоснованием, что передача дополнительного параметра в стеке при вызове cdecl не очень хорошо для быстродействия.

Попробовал поискать в интернете. Нашел вот это:
Как и большинство других операционных систем, Linux предоставляет т.н. API — набор полезных для программиста функций. В большинстве случаев вызов системной функции производится с помощью прерывания 80h. Следует отметить, что Linux используется fastcall-конвенция передачи параметров. Согласно ей параметры передаются через регистры (в windows, например, используется stdcall, где параметры передаются через стек).
http://habrahabr.ru/blogs/personal/79454/

Вызов через регистры - самый быстрый способ, но я боюсь, что вызове через регистры функций, написанных в разных средах (Delphi/Си) могут оказаться не совместимыми. Да и не понятно мне, если надо передать штук 10 параметров, а основных регистров всего 4 (AX, BX, CX, DX), то как будут передаваться остальные? В общем, через stdcall для windows проще реализовывать. Ну а при портировании на Unix можно или удалить stdcall или заранее написать макрос типа:
Код: Выделить всё
AFunction int Func1()
{
  ...
}
Новый проект AiKernel
Аватара пользователя
Prof1983
Серьёзный посетитель
 
Сообщения: 206
Зарегистрирован: Ср окт 11, 2006 13:29:31
Откуда: Новосибирск


Вернуться в Проект AIKernel

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


cron


Rambler's Top100 Каталог ресурсов ListTop.Ru Каталог сайтов Союз образовательных сайтов Parenting.ru - Родители семья дети ребенок

     Сайт "Искусственный интеллект" - программирование ИИ от разработчика: общение, статьи, ссылки.