Re[11]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 13:24
Оценка: +1
Здравствуйте, Andrew S, Вы писали:

R>>>>Что ты хочешь этим сказать? А ты погляди код, который генерируется при вызове функций, возвращающих значения. Там тоже есть код, там не по велению волшебной палочки всё происходит.


AS>>>Я хочу сказать, что там не 2-3 команды, а десяток довольно толстых как сточки зрения кода, так и данных, команд.


R>>>>Ситуация такая: при использовании исключений у функции есть пролог/эпилог, зато само тело меньше, т.к. нет постоянных проверок.

R>>>>при использовании возвращаемых значнеий — нет пролога/эпилога, зато каждый вызов функции/выделение ресурса обходится дороже.

R>>>>Вот именно это я исследовал. Что же в итоге лучше. Что перевешивает. То, что есть пролог/эпилог — это понятно, понятно, что это всё не за бесплатно.


AS>>>Чушь. Твоя запись if (!fun()) return val как раз не общий случай. Его я могу оптимизировать до одной проверки на все функции. val1 = fun1() ... valn = funn(); return val1 | val2 | ... | valn. В принципе, это может сделать и сам компилятор (более того, он это хоть и коряво, на пытается при помощи setne сделать). И что это покажет? Я говорю — нужны реальные паттерны.


R>>Это не оптимизация общего случая — пример — вложенные ресурсы.


AS>Это оптимизация приведенного тобой примера, в которой переход не требуется вообще...


Это понятно, что этот код можно оптимизировать. Я даже больше тебе скажу — весь этот код можно вообще удалить, т.к. он ровном счётом ничего не делает. И мерить это потом. Вот круто. Одна функция выполняется 0, и другая 0.
Суть как раз в том и заключается, что этой оптимизации нет и я эмулирую рельный код, в котором таких оптимизаций не будет. Только я выкинул из него весь шум в виде реальной работы, чтобы не вносить "постоянную составляющую".


R>>Ну допустим, я бы потратил пол-года и переписал некий проект bla-bla с одной стратегии на другую и выдал бы в итоге, что с исключениями bla-bla стал работать на 1% быстрее и размер уменьшился на 2%. Ну и что? По-твоему это бы дало больше информации?


AS>Не проект. Надо выделить несколько функций различных классов, и уже на их основе анализировать эффект.


R>>Мы же не штампуем целиком проекты, мы пишем отдельные функции — вот тут функци, которая форвардит вызов другой, а вот тут функция, которая вызывает ещё 3 функции, а вот тут функция, которая выделяет ресурс и т.д.


AS>Пустые функции — это не то. Ну сколько можно, право. Даже уже занятие ebp уменьшает вычислительный потенциал на несколько процентов.


R>>>>з.ы. кстати, если в функции нет объектов с нетривиальными деструкторами, то исключения выглядят значительно привлекательнее, т.к. и эпилога/пролога нет и вызовы функции дешевле.


AS>>>Не вышлядят. Блин, ну сколько можно — я ж уже показал, что в этом случае используется ebp стек фрейм. Попробуй лучше исследовать, как это влияет на перфоманс вычислительной функции, а?


R>>А я сколько раз показывал, что код работает на 50% быстрее и занимает на 200% меньше.


AS>Только ты показывал это на фикции — на пустых функциях. Которые к тому же можно оптимизировать в случае возвращаемых значений.


Да, всё правильно. Теперь ты можешь добавить в эти пустые функции своё наполнение, прибавить ко всем цифрам постоянную составляющую и получить те же результаты, но с постоянной составляющей.


AS>>>Я к чему — пустые функции должны идти в dev\null. Использование исключений значительно влияет на кодогенерацию. Точка.


R>>Так же как и возвращаемые значения. Очевидно. Осталось только понять как.


AS>А для этого надо как минимум анализировать результирующий код — чего сделано не было совсем. Ведь так? Ведь в результате (на мой взгляд) ты получил не эффект от использования исключений, а сравнение теплого с мягким...


Смотрел-смотрел. Просто я думал, что такой объём кода и так смотреть никто не бует, к тому же время уже подходило к часу ночи — хотелось домой


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[11]: Конструктив
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 13:26
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>Я к чему — пустые функции должны идти в dev\null. Использование исключений значительно влияет на кодогенерацию. Точка.


Давай же сформируем эти "общие паттерны". Как ты их себе видишь?
Я думаю, их будет полезно обсудить — все выскажут свои мысли. К тому же приверженцы обоих лагерей смогут предложить лучшие реализации того и другого подхода — чтобы никому не было обидно.




1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[12]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 13:40
Оценка:
R>>>А я сколько раз показывал, что код работает на 50% быстрее и занимает на 200% меньше.

AS>>Только ты показывал это на фикции — на пустых функциях. Которые к тому же можно оптимизировать в случае возвращаемых значений.


R>Да, всё правильно. Теперь ты можешь добавить в эти пустые функции своё наполнение, прибавить ко всем цифрам постоянную составляющую и получить те же результаты, но с постоянной составляющей.


Не получишь. Как минимум в одном случае у тебя на один рабочий регистр меньше — соответственно, меньше и производительность самой функции (а не пустышки). Право, я уже устал это повторять.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[12]: Конструктив
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 14:01
Оценка:
AS>>Я к чему — пустые функции должны идти в dev\null. Использование исключений значительно влияет на кодогенерацию. Точка.

R>Давай же сформируем эти "общие паттерны". Как ты их себе видишь?


Давай. Навскидку я вижу следующие паттерны:
1. Чисто вычислительная функция — когда вызовов апи не производится вообще. Это может быть быть парсер текста, вычисление с использованием матриц и т.п. Желательно распределить их по степени сложности — глубины вызовов и количеству вызовов с проверками в одной функции.
2. Обертки1. Когда ровно один слой и все сводится к вызову апи функции (или метода) и проверке возвращаемого значения\трансляции в исключение.
3. Обертки1. Тоже ровно один слой, но в этом случае апи использует исключение (пример — MFC). Мы транслируем в свое исключение либо в код ошибки\возвращаемое значение.
4. Работа с файлами и анализ текста. Микс тест из 1, 2 и 3.
5. Смешанные вычисления — когда необходимо в процессе вычислений обращаться к апи. Сложность вычислений,процент обращений и характер распределения мест обработки по уровням можно регулировать (либо определить статистически общие варианты и использовать только их).

Наверное, можно придумать еще кучу паттернов, используемых наиболее часто, либо параметризировать эти с учетом статистики.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re: [Investigation] Exceptions vs. Return Values
От: gear nuke  
Дата: 02.04.07 14:13
Оценка:
Здравствуйте, remark, Вы писали:

[]

R>

Размер кода


R>Так же есть ещё один аспект, влияющий на производительность, но который ускользает при таких замерах – размер сгенерированного кода. Чем больше кода – тем больше промахов кэша и переходов через границы страницы памяти – это может достаточно сильно влиять на производительность. Соответственно я замерил размер кода для одной функции типа f6(), которые я приводил выше. Результаты:

R>
с с++/rvс++/ex
instr 386 442 232
size 1320 2359 1329

R>Замерял на msvc71. instr – кол-во ассемблерных команд. Size – размер функции в байтах.

R>У исключений значительно меньше инструкций, тем не менее размер кода равен размеру кода на С с возвращаемыми значениями. Как ни странно... Связано с тем, что команды там больше по размеру. Код на С++ с возвращаемыми значениями тут сильно проигрывает – так там инструкции и на проверки возвращаемых значений и на поддержку исключений.


Интересно, почему С++ с возвращаемыми значениями так сильно проиграл С? А мне кажется, я знаю причину — оптимизатор MSVC отвратительно работает с bool типами, замена на int даёт выигрыш.

[]

R>

smart_ptr vs. smart_ptr&


Будете смеяться и писать про "root of all evil", но const int& быстрее и компактнее в коде, чем int. Особенно, когда куча шаблонных обёрток вызывает другие обёртки — оптимизатор не справляется с лишними копированиями...
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[5]: [Investigation] Exceptions vs. Return Values
От: gear nuke  
Дата: 02.04.07 14:27
Оценка: +1
Здравствуйте, CreatorCray, Вы писали:

CC>Увы, но более точного метода измерения кроме как

CC>
CC>    SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
CC>    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
CC>

CC>и rdtsc пока ИМХО никто не предложил...

Как минимум, можно использовать ещё и счётчики производительности (GetProcessTimes, NtQueryInformationThread + ThreadTimes). Даже без RDTSC погрешность измерения примерно равна длительности кванта планировщика (1-15 мс), что может оказаться лучше чем у способа выше, где она неизвестно какая
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[2]: [Investigation] Exceptions vs. Return Values
От: CreatorCray  
Дата: 02.04.07 14:41
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Будете смеяться и писать про "root of all evil", но const int& быстрее и компактнее в коде, чем int. Особенно, когда куча шаблонных обёрток вызывает другие обёртки — оптимизатор не справляется с лишними копированиями...

Однако... Это на каком компилере?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: Ассемблер для Andrew S
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 16:04
Оценка:

Exceptions vs. Return Values


Привожу полный код теста (для msvc):

файл 1.cpp:
#include <iostream>

typedef unsigned __int64 tick_t;
tick_t const max_tick = static_cast<tick_t>(-1);
__declspec(naked) tick_t get_tc()
{
    __asm rdtsc;
    __asm ret;
}

volatile int counter = 0;

struct tobj
{
    __declspec(noinline) tobj();
    __declspec(noinline) ~tobj();
    int fake;
};

__declspec(noinline) bool ctor(int*);
__declspec(noinline) void dtor(int*);

__declspec(noinline) void test_ex2()
{
    if (!++counter) throw 0;
}

__declspec(noinline) void test_ex()
{
    tobj o1, o2, o3, o4;
    test_ex2();
    test_ex2();
    test_ex2();
    test_ex2();
}

__declspec(noinline) bool test_rv2()
{
    return !!++counter;
}

__declspec(noinline) bool test_rv()
{
    int o1, o2, o3, o4;
    bool res = true;
    if (!ctor(&o1)) goto end;
    if (!ctor(&o2)) goto do1;
    if (!ctor(&o3)) goto do2;
    if (!ctor(&o4)) goto do3;
    if (!test_rv2()) goto do4;
    if (!test_rv2()) goto do4;
    if (!test_rv2()) goto do4;
    if (!test_rv2()) goto do4;
    res = true;
do4:    dtor(&o4);
do3:    dtor(&o3);
do2:    dtor(&o2);
do1:    dtor(&o1);
end:    return res;
}

int main()
{
    int const test_count = 10000;

    {
        int ec = 0;
        tick_t time = max_tick;
        tick_t start = 0;
        tick_t t = 0;
        for (int i = 0; i < test_count; ++i)
        {
            start = get_tc();
            try
            {
                test_ex();
            }
            catch (...)
            {
                ++ec;
            }
            t = get_tc() - start;
            if (t < time) time = t;
        }
        std::cout << "test_ex: " << time << "\n";
    }

    {
        int ec = 0;
        tick_t time = max_tick;
        tick_t start = 0;
        tick_t t = 0;
        for (int i = 0; i < test_count; ++i)
        {
            start = get_tc();
            if (!test_rv())
                ++ec;
            t = get_tc() - start;
            if (t < time) time = t;
        }
        std::cout << "test_rv: " << time << "\n";
    }
}




файл 2.cpp:
struct tobj
{
    __declspec(noinline) tobj();
    __declspec(noinline) ~tobj();
};

tobj::tobj() {}
tobj::~tobj() {}

__declspec(noinline) bool ctor(int*) {return true;}
__declspec(noinline) void dtor(int*) {}




Листинг:
__declspec(noinline) void test_ex()
{
// Вот создаём фрейм - 6 команд
00401040  push        0FFFFFFFFh 
00401042  push        offset __ehhandler$?test_ex@@YAXXZ (401750h) 
00401047  mov         eax,dword ptr fs:[00000000h] 
0040104D  push        eax  
0040104E  mov         dword ptr fs:[0],esp 
00401055  sub         esp,10h 
    tobj o1, o2, o3, o4;
// Вот вызываем 4 конструктора - 4 по 3 команды
00401058  lea         ecx,[esp+0Ch] 
0040105C  call        tobj::tobj (401300h) 
00401061  lea         ecx,[esp+8] 
00401065  mov         dword ptr [esp+18h],0 
0040106D  call        tobj::tobj (401300h) 
00401072  lea         ecx,[esp+4] 
00401076  mov         byte ptr [esp+18h],1 
0040107B  call        tobj::tobj (401300h) 
00401080  lea         ecx,[esp] 
00401083  mov         byte ptr [esp+18h],2 
00401088  call        tobj::tobj (401300h) 
0040108D  mov         byte ptr [esp+18h],3 
// Вот вызываем 4 функции - 4 команды
    test_ex2();
00401092  call        test_ex2 (401010h) 
    test_ex2();
00401097  call        test_ex2 (401010h) 
    test_ex2();
0040109C  call        test_ex2 (401010h) 
    test_ex2();
004010A1  call        test_ex2 (401010h) 
}
// Вызываем 4 деструктора - 4 по 3 инструкции
004010A6  lea         ecx,[esp] 
004010A9  mov         byte ptr [esp+18h],2 
004010AE  call        dtor (401320h) 
004010B3  lea         ecx,[esp+4] 
004010B7  mov         byte ptr [esp+18h],1 
004010BC  call        dtor (401320h) 
004010C1  lea         ecx,[esp+8] 
004010C5  mov         byte ptr [esp+18h],0 
004010CA  call        dtor (401320h)
// Снимаем фрейм исключений - 6 инструкций 
004010CF  lea         ecx,[esp+0Ch] 
004010D3  mov         dword ptr [esp+18h],0FFFFFFFFh 
004010DB  call        dtor (401320h) 
004010E0  mov         ecx,dword ptr [esp+10h] 
004010E4  mov         dword ptr fs:[0],ecx 
004010EB  add         esp,1Ch 
004010EE  ret




__declspec(noinline) bool test_rv()
{
    int o1, o2, o3, o4;
    bool res = true;
    if (!ctor(&o1)) goto end;
// Вызываем 4 конструктора - 4 по 6 инструкций
00401110  lea         eax,[esp-4] 
00401114  sub         esp,10h 
00401117  push        eax  
00401118  call        ctor (401310h) 
0040111D  add         esp,4 
00401120  test        al,al 
00401122  je          do1+0Dh (4011ADh) 
    if (!ctor(&o2)) goto do1;
00401128  lea         ecx,[esp+8] 
0040112C  push        ecx  
0040112D  call        ctor (401310h) 
00401132  add         esp,4 
00401135  test        al,al 
00401137  je          do1 (4011A0h) 
    if (!ctor(&o3)) goto do2;
00401139  lea         edx,[esp+4] 
0040113D  push        edx  
0040113E  call        ctor (401310h) 
00401143  add         esp,4 
00401146  test        al,al 
00401148  je          do2 (401193h) 
    if (!ctor(&o4)) goto do3;
0040114A  lea         eax,[esp] 
0040114D  push        eax  
0040114E  call        ctor (401310h) 
00401153  add         esp,4 
00401156  test        al,al 
00401158  je          do3 (401186h) 

// Вызываем 4 функции - 4 по 3 инструкции
    if (!test_rv2()) goto do4;
0040115A  call        test_rv2 (4010F0h) 
0040115F  test        al,al 
00401161  je          do4 (40117Ah) 
    if (!test_rv2()) goto do4;
00401163  call        test_rv2 (4010F0h) 
00401168  test        al,al 
0040116A  je          do4 (40117Ah) 
    if (!test_rv2()) goto do4;
0040116C  call        test_rv2 (4010F0h) 
00401171  test        al,al 
00401173  je          do4 (40117Ah) 
    if (!test_rv2()) goto do4;
00401175  call        test_rv2 (4010F0h) 
    res = true;
// Вызываем 4 деструктора - 4 по 4 инструкции
do4:    dtor(&o4);
0040117A  lea         ecx,[esp] 
0040117D  push        ecx  
0040117E  call        dtor (401320h) 
00401183  add         esp,4 
do3:    dtor(&o3);
00401186  lea         edx,[esp+4] 
0040118A  push        edx  
0040118B  call        dtor (401320h) 
00401190  add         esp,4 
do2:    dtor(&o2);
00401193  lea         eax,[esp+8] 
00401197  push        eax  
00401198  call        dtor (401320h) 
0040119D  add         esp,4 
do1:    dtor(&o1);
004011A0  lea         ecx,[esp+0Ch] 
004011A4  push        ecx  
004011A5  call        dtor (401320h) 
004011AA  add         esp,4 
end:    return res;
004011AD  mov         al,1 
}
004011AF  add         esp,10h 
004011B2  ret




Итого время выполнения:
ex — 172
rv — 184



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: [Investigation] Exceptions vs. Return Values
От: remark Россия http://www.1024cores.net/
Дата: 02.04.07 16:09
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Интересно, почему С++ с возвращаемыми значениями так сильно проиграл С? А мне кажется, я знаю причину — оптимизатор MSVC отвратительно работает с bool типами, замена на int даёт выигрыш.



Нет, там проблема не в этом.
Там проблема, в том, что есть деструкторы — значит устанавливается и снимается фрейм исключений — т.е. тут двойная работа.
А код С++ компилятор даже лучше генерирует — поскольку деструкторы не вызываются явно у него есть некая свобода в оптимизации.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: Ассемблер для Andrew S
От: Аноним  
Дата: 02.04.07 16:18
Оценка:
Здравствуйте, remark, Вы писали:

R>

Exceptions vs. Return Values


R>Привожу полный код теста (для msvc):


R>файл 1.cpp:

R>
R>#include <iostream>

R>typedef unsigned __int64 tick_t;
R>tick_t const max_tick = static_cast<tick_t>(-1);
R>__declspec(naked) tick_t get_tc()
R>{
R>    __asm rdtsc;
R>    __asm ret;
R>}


Кстати rdtsc темное место на многоядерных и винапи коунтеры тоже
Re[3]: [Investigation] Exceptions vs. Return Values
От: gear nuke  
Дата: 02.04.07 17:03
Оценка:
Здравствуйте, remark, Вы писали:

R>Там проблема, в том, что есть деструкторы — значит устанавливается и снимается фрейм исключений — т.е. тут двойная работа.


Я о "с++/rv"

R>А код С++ компилятор даже лучше генерирует — поскольку деструкторы не вызываются явно у него есть некая свобода в оптимизации.


Не верю Компилятор там один и тот же.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[3]: MSVC 2005 [-]
От: gear nuke  
Дата: 02.04.07 17:23
Оценка:
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[2]: Ассемблер для Andrew S
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 17:29
Оценка: +1
[code skipped]

Нда, сильно. Вот почему я и говорю о необходимости кода.
1. Тест в общем случае некорректен. В случае использования возвращаемого значения использовать идиому RAI нет необходимости, поэтому первые 4 сравнения идут лесом. Про что я и говорил — различные варианты обработки ошибок влекут использование различных паттернов на различных уровнях вызова.
2. Вариант с rv у тебя с ошибкой
3. Где случай, в котором тебе надо вызывать функцию вне зависимости от результата вызова предыдущей? Т.е. вызвали одну, затем другую, затем третью и т.д. — а потом обрабатываем результат в зависимости от вызова. Т.е. не &&, а ||.
4. Где вложенная обработка исключений, тоже непонятно. Впрочем, это боком относится к (3), но все же? Например, некоторые искючения могут позволить продолжить цикл (info\warning), тогда как другие ведут к выходу.
5. Обрати внимание, что в rv варианте используется esp стек фрейм, а в ex — может и ebp. О чем я тебе уже 100 раз говорил. Итого — мало-мальски сложный код в ex модели будет тормознее, чем в rv. Тот пример у тебя, слишком прост, чтобы это отобразить. Вот, посмотри, что получается в этом случае:


static void test_ex()
{
    tobj o1, o2, o3, o4;
    try
    {
        test_ex2();
        test_ex2();
        test_ex2();
        test_ex2();
    }
    catch(...)
    {
    }
}


6. Обрати внимание на разницу в способе вызова — в случае ex для настоящих объектов у тебя используеся this_call. Попробуй сделать не эмуляцию контрукторов функциями, а сделать init\deinit в самом tobj. Это съэкономит прилично и места, и времени.
7. Исключения должны быть более сложными — иметь иерархию классов — про это уже говорили. Это позволит устроить уровни отсечения.

А вообще, проблема на мой взгляд вот в чем. Ты берешь за основу модель исключений, и пытаешься приспособить под нее модель возвращаемых значений. Об этом говорит и использование bool в качестве возвращаемого значения (тогда как используется обычно более информативные типы, возвращающие не только успешность, но и саму ошибку — т.е. информации в разы больше), и построение функции (очередность и кратность вызова), уровень обработки (исключение у тебя обрабатывается на самом высоком уровне, тогда как общая практика — обработка части исключений на различных уровнях вызова, добавление отработки даже на одном уровне — то, что ты называешь ресурсами, уже изменяет ситуацию) и т.д. Неудивительно, что в этих условиях rv почти всегда проигрывает. У тебя полностью сферический конь в полном отсутствии воздуха. Я уже неоднократно говорил, что придумать ситуации, когда ex или rv будет выигрывать проблем не составляет. Нас должно интересовать не это, а реально существующие паттерны кода.

PS Эк тебя зацепило Критику надо воспринимать не в штыки, а пытаться хотя бы слушать оппонента.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[12]: [Investigation] Exceptions vs. Return Values
От: minorlogic Украина  
Дата: 02.04.07 17:51
Оценка: 1 (1) +1
Здравствуйте, Andrew S, Вы писали:

AS>>>Да. Сильно. А ты не подумал, что выбор минимального из результатов — это в корне неправильный подход к статистике?


M>>Статистика тут ни при чем. В подобныъ замерах скорости — интерес представляет только минимальное время выполнения.


AS>Ух ты. Т.е. в реальной жизни пользователь запускает программу и всегда попадает на минимум? Везет...


Нет , тут дело в методике измерений. Есть масса причин для замедления времени выполнения (прерывания и т.п.), но нет ни ЕДИНОЙ причины , для того чтобы код выполнялся быстрее в какой то из разов.


M>>То есть у вас есть лучшее тестирование , и вы его зажимаете и не выкладываете ?


AS>Я где-то такое говорил?


По постам сложилось впечатление , раз вы знаете и умеете все лучше чем автор топика.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[2]: [Investigation] Exceptions vs. Return Values
От: Аноним  
Дата: 02.04.07 18:09
Оценка: 1 (1)
Здравствуйте, gear nuke, Вы писали:

GN>Будете смеяться и писать про "root of all evil", но const int& быстрее и компактнее в коде, чем int. Особенно, когда куча шаблонных обёрток вызывает другие обёртки — оптимизатор не справляется с лишними копированиями...


1 — передача адреса без чтония памяти. la заместо mov
2 — Может E(ABCD)X кончильсь, а указатели остались.
3 — Уж во всяком случае не всегда так
Re[13]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 18:11
Оценка:
AS>>>>Да. Сильно. А ты не подумал, что выбор минимального из результатов — это в корне неправильный подход к статистике?

M>>>Статистика тут ни при чем. В подобныъ замерах скорости — интерес представляет только минимальное время выполнения.


AS>>Ух ты. Т.е. в реальной жизни пользователь запускает программу и всегда попадает на минимум? Везет...


M>Нет , тут дело в методике измерений. Есть масса причин для замедления времени выполнения (прерывания и т.п.), но нет ни ЕДИНОЙ причины , для того чтобы код выполнялся быстрее в какой то из разов.


Ух ты какое сильное заявление. Причин может быть куча — выполнение на разных процессорах, состояние кеш-памяти, размер физической памяти и файла подкачки и многое многое другое. Все это может вести к выпадениям как меньшую, так и в большую сторону, тогда как в 99% процентах случаев разброс будет около некоей средней величины. Или опять интересует поведение сферического коня в вакууме? Тогда лучше всего в этом смысле тестировать в системах типа DOS. А тут же обычная практика — отсечение значений, которые выходят за некоторую границу (как сверху, так и снизу), и вычисление среднего относительно остальных.

M>>>То есть у вас есть лучшее тестирование , и вы его зажимаете и не выкладываете ?


AS>>Я где-то такое говорил?


M>По постам сложилось впечатление , раз вы знаете и умеете все лучше чем автор топика.


Фраза как минимум несогласована — моя твоя есть с трудом понимайт. Ну а касательно ваших впечатлений — ну это сугубо ваше дело, зачем это на форум то писать? Есть конструктив по поводу тестов? У меня вот есть. А у вас?
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[14]: [Investigation] Exceptions vs. Return Values
От: minorlogic Украина  
Дата: 02.04.07 18:16
Оценка:
Я не хочу ничего объяснять , если вас заинтересовал этот вопрос , почитайте Криса Касперски.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[15]: [Investigation] Exceptions vs. Return Values
От: Andrew S Россия http://alchemy-lab.com
Дата: 02.04.07 18:33
Оценка:
M>Я не хочу ничего объяснять , если вас заинтересовал этот вопрос , почитайте Криса Касперски.

Так, давайте, что именно? Или просто "отвяжись" — дык тогда может лучше так и говорить?
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[3]: [Investigation] Exceptions vs. Return Values
От: gear nuke  
Дата: 02.04.07 18:57
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>1 — передача адреса без чтония памяти. la заместо mov


Имеется ввиду команда lea? Не пойму, как она может быть лучше.

А>2 — Может E(ABCD)X кончильсь, а указатели остались.


Указатели, как и данные, могут храниться в любом регистре.

Но речь о случае, когда данные (а тем более указатели) вообще не нужно передавать посредством копирования, в функциях вида:
template <typename T>
static inline
bool f(T a, T a2) { return f_impl(a, a2); }
вообще никакой код не должен быть сгенерирован. В современном коде часто встречаются многократные вложения таких примитивных функций, и оптимизатор сдаёт, делая лишние копирования в регистры даже при inline подстановке функций для типа int.

Ещё хуже для UDT типов малого размера (как раз смартпоинтеры)
struct  { int _; };
Вполне можно работать с этим типом как с простым int, но компилятор опять же вставляет лишние копирования.

Вот только вчера столкнулся с растущим отсюда багом:

struct kirql { uint8_t level; };

extern "C" __declspec(dllimport)
void __fastcall
  KfReleaseSpinLock(
    kspin_lock *  SpinLock,
    const kirql   NewIrql
    );

void kspin_lock::release(const kirql new_irql)
{
  KfReleaseSpinLock(this, new_irql);
}

При удачной оптимизации это компелируется (и должно!) в:
?release@kspin_lock@km@ntl@@QAEXUkirql@23@@Z PROC   ; ntl::km::kspin_lock::release, COMDAT
; _this$ = ecx
; Line 71
    jmp DWORD PTR __imp_@KfReleaseSpinLock@8
?release@kspin_lock@km@ntl@@QAEXUkirql@23@@Z ENDP   ; ntl::km::kspin_lock::release

Однако при отключенной (дебаг) получается чушь:
_this$ = -4                     ; size = 4
_new_irql$ = 8                      ; size = 1
?release@kspin_lock@km@ntl@@QAEXUkirql@23@@Z PROC   ; ntl::km::kspin_lock::release, COMDAT
; _this$ = ecx
; Line 70
    push    ebp
    mov ebp, esp
    push    ecx
    mov DWORD PTR _this$[ebp], ecx
; Line 71
    mov al, BYTE PTR _new_irql$[ebp]
    push    eax                  ; вот этот параметр следует передавать в регисте edx, а не через стек 
    mov ecx, DWORD PTR _this$[ebp]
    call    DWORD PTR __imp_@KfReleaseSpinLock@8
; Line 72
    mov esp, ebp
    pop ebp
    ret 4
?release@kspin_lock@km@ntl@@QAEXUkirql@23@@Z ENDP   ; ntl::km::kspin_lock::release
; Function compile flags: /Odtp
_TEXT   ENDS


А>3 — Уж во всяком случае не всегда так


Ну да, часто нет разницы
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[16]: [Investigation] Exceptions vs. Return Values
От: minorlogic Украина  
Дата: 02.04.07 19:48
Оценка:
Здравствуйте, Andrew S, Вы писали:

M>>Я не хочу ничего объяснять , если вас заинтересовал этот вопрос , почитайте Криса Касперски.


AS>Так, давайте, что именно? Или просто "отвяжись" — дык тогда может лучше так и говорить?


начать можно тут
http://www.codenet.ru/progr/optimize/kk/
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.