Re[28]: C# - from indians by indians
От: PM  
Дата: 05.06.15 19:38
Оценка: 2 (1)
Здравствуйте, Sinix, Вы писали:

S>У меня какая-то ересь получается.

S>VS2013, релиз, win32, без отладчика на настройках проекта по умолчанию выдаёт
S>
S>Elapsed = 189.011 ms
S>


В Visual C++ 2013 std::chrono::high_resolution_clock сломан https://connect.microsoft.com/VisualStudio/feedback/details/719443/c-chrono-headers-high-resolution-clock-does-not-have-high-resolution
Re[29]: C# - from indians by indians
От: Evgeny.Panasyuk Россия  
Дата: 05.06.15 19:44
Оценка: +1
Здравствуйте, PM, Вы писали:

S>>У меня какая-то ересь получается.

S>>VS2013, релиз, win32, без отладчика на настройках проекта по умолчанию выдаёт
S>>
S>>Elapsed = 189.011 ms
S>>

PM>В Visual C++ 2013 std::chrono::high_resolution_clock сломан https://connect.microsoft.com/VisualStudio/feedback/details/719443/c-chrono-headers-high-resolution-clock-does-not-have-high-resolution

Там говорится что точность недостаточна, но ведь не на столько же — тут же речь идёт о лишней сотне миллисекунд.
Re[30]: C# - from indians by indians
От: PM  
Дата: 05.06.15 21:25
Оценка: 3 (2)
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Там говорится что точность недостаточна, но ведь не на столько же — тут же речь идёт о лишней сотне миллисекунд.


Верно, дело не в точности, N достаточно велико. Это чудит микрософтовский компилятор — сопоставимого времени (50 ms) с C# вариантом (65 ms) удалось добиться только для x64, сделав передачу аргументов по ссылке

Complex operator*(Complex const& x, Complex const& y);

transform(begin(v), end(v), begin(u), begin(v), [](Complex const& x, Complex const& y)
{
    return x*y;
});
Re[31]: C# - from indians by indians
От: Evgeny.Panasyuk Россия  
Дата: 05.06.15 21:47
Оценка:
Здравствуйте, PM, Вы писали:

PM>Верно, дело не в точности, N достаточно велико. Это чудит микрософтовский компилятор — сопоставимого времени (50 ms) с C# вариантом (65 ms) удалось добиться только для x64,


У меня по-умолчанию было x32, для x64 результат примерно такой же — разницы на 100ms нет.

PM>сделав передачу аргументов по ссылке


У GCC ASM идентичный в обоих случаях. Если у MSVC из-за этого такая разница — то нужно отправлять report, так как случай тривиальный.
Re[32]: C# - from indians by indians
От: PM  
Дата: 05.06.15 23:37
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

PM>>Верно, дело не в точности, N достаточно велико. Это чудит микрософтовский компилятор — сопоставимого времени (50 ms) с C# вариантом (65 ms) удалось добиться только для x64,


EP>У меня по-умолчанию было x32, для x64 результат примерно такой же — разницы на 100ms нет.


PM>>сделав передачу аргументов по ссылке


EP>У GCC ASM идентичный в обоих случаях. Если у MSVC из-за этого такая разница — то нужно отправлять report, так как случай тривиальный.


Попробовал на Visual C++2015 RC, передача аргументов по ссылке: ~50 мс, по значению: ~60 мс. Сгенерированный код смотреть даже и не хочется, скорее всего VC2013 не осилил заинлайнить benchmark и std::transform

Думаю, репорт уже не поможет — МС не любит чинить баги в предыдущих версиях Visual C++. Где-то я читал, что обновлений для Visual C++2013 больше не будет. Видимо все силы брошены на выпуск новой версии.
Re[27]: C# - from indians by indians
От: greenpci  
Дата: 06.06.15 00:20
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

G>>А вот List, похоже, тормозит из-за проверки индекса, которую нельзя убрать, с помощью unsafe


Кстати, я забыл поставить unchecked вчера и никто не заметил.

unchecked
{
  for (int i = 0; i < n; i++)
  {
    v[i] = v[i] * u[i];
  }
}


.NET Elapsed: 102.0000 ms
Elapsed = 93.6 ms        
.NET Elapsed: 102.0000 ms
Elapsed = 93.601 ms      
.NET Elapsed: 104.0000 ms
Elapsed = 78.001 ms      
.NET Elapsed: 105.0000 ms
Elapsed = 78 ms          
.NET Elapsed: 101.0000 ms
Elapsed = 78 ms          
.NET Elapsed: 105.0000 ms
Elapsed = 78 ms          
.NET Elapsed: 109.0000 ms
Elapsed = 93.6 ms        
.NET Elapsed: 107.0000 ms
Elapsed = 78.001 ms      
.NET Elapsed: 106.0000 ms
Elapsed = 78 ms          
.NET Elapsed: 107.0000 ms
Elapsed = 78 ms


EP>Не думаю что из-за проверки индекса будет такая разница — branch predictor должен с ней неплохо справится. Желательно посмотреть какой там ASM получается.


Смотри цифры наверху. Но это от unchecked и массива. То есть, немного другой случай.

EP>На MSVC++ если использовать std::vector::at, внутри которого такая же проверка, то там разница на десятки процентов а не в разы.


Согласен. Я это и имел ввиду. На десятки процентов, а то и меньше.

UPD:

не, не обращайте внимание. Сравнил IL, он такой же. Просто моя машина сегодня немножко быстрее работает Тем более, что калькуляция вообще не там происходит.
Отредактировано 06.06.2015 4:22 greenpci . Предыдущая версия . Еще …
Отредактировано 06.06.2015 3:56 greenpci . Предыдущая версия .
Re: C# - from indians by indians
От: -n1l-  
Дата: 06.06.15 00:30
Оценка:
В щарпе геттер делается не методами а свойствами, поля не нужны(практически никогда), но да что бы прям как конст такого нет.
В другом случае если ваш коллега пхд из индии может залезть в исходники он может ваш конст убрать.
Re[33]: C# - from indians by indians
От: Evgeny.Panasyuk Россия  
Дата: 06.06.15 07:51
Оценка:
Здравствуйте, PM, Вы писали:

PM>Попробовал на Visual C++2015 RC, передача аргументов по ссылке: ~50 мс, по значению: ~60 мс. Сгенерированный код смотреть даже и не хочется, скорее всего VC2013 не осилил заинлайнить benchmark и std::transform


На VS2012 ситуация следующая:
* во всех четырёх вариантах сам transform не инлайнится (для этого теста особо без разницы)
* все внутренности transform заинлайнены (лямбда, оператор)
* на x32 отличие в ASM минимальное, отличие в скорости незаметно
* на x64 в версии по значению появляется код с лишними обращениями к стэку, отличие по скорости по этому таймеру около 10ms.

PM>Думаю, репорт уже не поможет — МС не любит чинить баги в предыдущих версиях Visual C++. Где-то я читал, что обновлений для Visual C++2013 больше не будет. Видимо все силы брошены на выпуск новой версии.


Тут две проблемы:
* одна про то что на VS2013 (на ней же тормоза были?) в трёх версиях появляется разница в 100ms — её видимо в 2015 уже пофиксили
* сильное отличие кода между вариантами на x64, которого нет на x32 — она по всей видимости осталась. Подобного кода много даже в самом стандарте — функциональные объекты в алгоритмах, std::next/prev и т.д.
Re[28]: C# - from indians by indians
От: Evgeny.Panasyuk Россия  
Дата: 06.06.15 08:27
Оценка:
Здравствуйте, greenpci, Вы писали:

G>>>А вот List, похоже, тормозит из-за проверки индекса, которую нельзя убрать, с помощью unsafe

G>Кстати, я забыл поставить unchecked вчера и никто не заметил.

Забыл/не забыл зависит от того что именно ты хотел протестировать. А так, если интересно, то можешь ещё и на указателях попробовать через fixed.
Re[28]: C# - from indians by indians
От: mik1  
Дата: 06.06.15 11:41
Оценка: 1 (1) +1
Здравствуйте, greenpci, Вы писали:

G>Кстати, я забыл поставить unchecked вчера и никто не заметил.


G>
G>unchecked
G>{
G>  for (int i = 0; i < n; i++)
G>  {
G>    v[i] = v[i] * u[i];
G>  }
G>}
G>


Ты уверен, что в шарпе ты с бубном танцевал меньше, чем я в Яве?
Кстати, в Яве объекты дают только 3.5х просадку (~185мс против 58 мс) в отличии от полного ужоса шарпа (~4700 мс против 110 мс).

С опциями JVM, кстати, я не игрался в этом тесте. В отличии от...
Re[29]: C# - from indians by indians
От: greenpci  
Дата: 06.06.15 11:51
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Забыл/не забыл зависит от того что именно ты хотел протестировать. А так, если интересно, то можешь ещё и на указателях попробовать через fixed.


Филосовский вопрос в следующем. Можно ли будет этот код на указателях и fixed назвать шарпом, или это будет Си плюс плюсная вставка в шарп?! Наподобие asm в си и паскале.

Я хотел понять для себя, можно ли написать управляемых код, который будет таким же быстрым, как Си плюс плюс, в рамках этой задачи. На данный момент, делаю вывод, что нельзя. Будет разница в пользу плюсов. То есть плюсы бытсрее.

И больше склоняюсь к выводу, что эти утверждения внизу ложны:

mik1 писал:

2) Я не думаю, что с byte[] в Яве управляться труднее, чем в плюсах. Соот-но, время и пространство не факт, что ухудшатся.



UPD: хотя вот в этом утверждении ниже unmanaged, и уже встает вопрос, зачем тогда вообще писать на шарпе.

gandjustas писал:

А с unmanaged можно писать на C# как на С (c соответствующими скоростями)

Отредактировано 06.06.2015 12:16 greenpci . Предыдущая версия .
Re[29]: C# - from indians by indians
От: greenpci  
Дата: 06.06.15 11:57
Оценка:
Здравствуйте, mik1, Вы писали:

M>Ты уверен, что в шарпе ты с бубном танцевал меньше, чем я в Яве?


нет, я ставлю вопрос managed vs C++, а не C# vs Java. Я слишком плохо знаю джаву для второго. На текущий момент, плюсы рулят и по скорости и по приятности кода.

M>Кстати, в Яве объекты дают только 3.5х просадку (~185мс против 58 мс) в отличии от полного ужоса шарпа (~4700 мс против 110 мс).


Не утешает. Обе просадки для моей задачи не допустимы.

M>С опциями JVM, кстати, я не игрался в этом тесте. В отличии от...


С плюсами тоже можно еще поиграться. Взять компилятор от интел, например.
Re[29]: C# - from indians by indians
От: Evgeny.Panasyuk Россия  
Дата: 06.06.15 12:32
Оценка:
Здравствуйте, mik1, Вы писали:

M>Кстати, в Яве объекты дают только 3.5х просадку (~185мс против 58 мс) в отличии от полного ужоса шарпа (~4700 мс против 110 мс).


У тебя наверное без перемешивания — а на C# насколько я помню был shuffle

UPD: Ну да, вот
Автор: greenpci
Дата: 05.06.15
же он:
G>
G>        public static void Shuffle<T>(IList<T> list)
G>        {
G>            Random rng = new Random();
G>            int n = list.Count;
G>            while (n > 1)
G>            {
G>                n--;
G>                int k = rng.Next(n + 1);
G>                T value = list[k];
G>                list[k] = list[n];
G>                list[n] = value;
G>            }
G>        }

G>        public static void PopulateWithRandom(Complex[] v, Complex[] u)
G>        {
G>            const int n = 1 << 24;
G>            for (int i = 0; i < n; i++ )
G>            {
G>                Complex random = Complex.RandomComplex();
G>                v[i] = random;
G>                u[i] = random;
G>            }

G>            Funcs.Shuffle(u);
G>            Funcs.Shuffle(v);
G>        }
Отредактировано 06.06.2015 12:45 Evgeny.Panasyuk . Предыдущая версия .
Re[30]: C# - from indians by indians
От: Evgeny.Panasyuk Россия  
Дата: 06.06.15 13:07
Оценка: 1 (1) +1
Здравствуйте, greenpci, Вы писали:

EP>>Забыл/не забыл зависит от того что именно ты хотел протестировать. А так, если интересно, то можешь ещё и на указателях попробовать через fixed.

G>Филосовский вопрос в следующем. Можно ли будет этот код на указателях и fixed назвать шарпом, или это будет Си плюс плюсная вставка в шарп?! Наподобие asm в си и паскале.

Это всё же будет C#, но такой код будет называться C-style. В Java даже этого нельзя — там будет C-minus-structs-style.
Точно также как на C++ можно писать в Java-style с кучей лишних индерекций, аллокаций, избыточным динамическим полиморфизмом и раздутыми иерархиями, и за это справедливо получать тормоза.

G>Я хотел понять для себя, можно ли написать управляемых код, который будет таким же быстрым, как Си плюс плюс, в рамках этой задачи. На данный момент, делаю вывод, что нельзя. Будет разница в пользу плюсов. То есть плюсы бытсрее.


Справедливости ради, эти десятки процентов не такая уж и значительная разница. Могу ещё раз повторится — и на Java и на C# можно писать быстрый код, но на C++ быстрый код получить на порядки проще. Даже есть вот такая цитата:

"The going word at Facebook is that 'reasonably written C++ code just runs fast,' which underscores the enormous effort spent at optimizing PHP and Java code. Paradoxically, C++ code is more difficult to write than in other languages, but efficient code is a lot easier [to write in C++ than in other languages]." – Herb Sutter at //build/, quoting Andrei Alexandrescu

Отредактировано 06.06.2015 13:09 Evgeny.Panasyuk . Предыдущая версия .
Re[31]: C# - from indians by indians
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 06.06.15 14:21
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Справедливости ради, эти десятки процентов не такая уж и значительная разница. Могу ещё раз повторится — и на Java и на C# можно писать быстрый код, но на C++ быстрый код получить на порядки проще. Даже есть вот такая цитата:

EP>

EP>"The going word at Facebook is that 'reasonably written C++ code just runs fast,' which underscores the enormous effort spent at optimizing PHP and Java code. Paradoxically, C++ code is more difficult to write than in other languages, but efficient code is a lot easier [to write in C++ than in other languages]." – Herb Sutter at //build/, quoting Andrei Alexandrescu


Не стоит верить на слово в такие цитаты.
Во-первых fb переписал добрую половину STL, что уже недоступно в любом среднем проекте и большинстве крупных.
Во-вторых проценты прироста быстродействия в масштабах ФБ это десятки и сотни серверов, и это действительно стоит затраченных сотен тысяч и миллионов долларов на ЗП программистов.

Для большинства проектов проценты прироста быстродействия останутся незамеченными и дешевле будет сделать апгрейд железа, чем заниматься оптимизацией. Поэтому утверждение что "на C++ быстрый код получить на порядки проще" не имеет никакого смысла и верно только в контексте фейсбука\гугла и еще пары-тройки гигантов. В остальных случаях сложность оптимизации на C++ и C# (и иногда Java) сравнимы, а учитывая в общем более высокую сложность разработки на C++ еще непонятно что будет проще в итоге.

ЗЫ. При этом никто не сомневается что предел оптимизации программы на C++ выше, чем для C# или Java. Но достижение этого предела превышает в большинстве случаев выльется в слишком большие затраты.
Re[32]: C# - from indians by indians
От: Evgeny.Panasyuk Россия  
Дата: 06.06.15 14:50
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Не стоит верить на слово в такие цитаты.


Не верить в то что такая цитата была? Можем проверить.
Или в то что так на самом деле? Весь топик выше как раз это и демонстрирует

G>Во-первых fb переписал добрую половину STL, что уже недоступно в любом среднем проекте и большинстве крупных.


1. И какой ты делаешь из этого вывод?
2. У них есть оптимизации некоторых контейнеров под их нужды — это далеко не половина STL. Причём в "среднем проекте" в котором я работаю есть подобные оптимизированные контейнеры, а один из них вообще точь в точь такой же (когда делал они ещё не выложили свой на github).

G>Во-вторых проценты прироста быстродействия в масштабах ФБ это десятки и сотни серверов, и это действительно стоит затраченных сотен тысяч и миллионов долларов на ЗП программистов.


Тезис в цитате (с которым я полностью согласен) довольно прост — на C++ проще создать быстрый код. Ты же пытаешься передёрнуть в какую-то совершенно другую плоскость

G>Для большинства проектов проценты прироста быстродействия


Причём тут "проценты"?
Выше как раз показано что при использовании Java-style это не проценты, а разы, и даже порядки.

G>останутся незамеченными и дешевле будет сделать апгрейд железа, чем заниматься оптимизацией. Поэтому утверждение что "на C++ быстрый код получить на порядки проще" не имеет никакого смысла и верно только в контексте фейсбука\гугла и еще пары-тройки гигантов.


Ты почему-то говоришь в контексте каких-то отдельных областей типа web'а — причём так, что как-будто ничего другого нет. Уж поверь "быстрый код на C++" нужен не только гигантам.
Тебе попадаются задачи где не нужен? Поздравляю, вот только не надо необоснованно экстраполировать свой опыт на всю индустрию.

G>В остальных случаях сложность оптимизации на C++ и C# (и иногда Java) сравнимы, а учитывая в общем более высокую сложность разработки на C++ еще непонятно что будет проще в итоге.


Нет, не сравнимы. В C++ я могу сделать много уровней абстракций, которые будут либо бесплатными, либо крайне дешёвыми. В C#, а тем более Java, так не получится. И вот за счёт этого получается проще.

G>ЗЫ. При этом никто не сомневается что предел оптимизации программы на C++ выше, чем для C# или Java. Но достижение этого предела превышает в большинстве случаев выльется в слишком большие затраты.


Мой поинт наоборот противоположный, и я уже устал его повторять:
Предел оптимизации везде примерно одинаковый, разница в десятки процентов это не так уж серьёзно. Но на C++ этот предел гораздо проще достичь.
Re[33]: C# - from indians by indians
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 06.06.15 16:19
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Тезис в цитате (с которым я полностью согласен) довольно прост — на C++ проще создать быстрый код. Ты же пытаешься передёрнуть в какую-то совершенно другую плоскость

Плоскость та же самая. Просто ответь на вопрос насколько проще и насколько нужна скорость с учетом всех факторов, потому что для сравнительных факторов нужна база для сравнения, иначе рассуждения ни о чем.

G>>Для большинства проектов проценты прироста быстродействия


EP>Причём тут "проценты"?

EP>Выше как раз показано что при использовании Java-style это не проценты, а разы, и даже порядки.
А при использовании C# не разы. Кроме того операции с complex не такой уж частый случай. Я вот сомневаюсь что в том же ФБ много кода, работающего с вещественными числами.


G>>останутся незамеченными и дешевле будет сделать апгрейд железа, чем заниматься оптимизацией. Поэтому утверждение что "на C++ быстрый код получить на порядки проще" не имеет никакого смысла и верно только в контексте фейсбука\гугла и еще пары-тройки гигантов.


EP>Ты почему-то говоришь в контексте каких-то отдельных областей типа web'а — причём так, что как-будто ничего другого нет. Уж поверь "быстрый код на C++" нужен не только гигантам.

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


EP>Тебе попадаются задачи где не нужен? Поздравляю, вот только не надо необоснованно экстраполировать свой опыт на всю индустрию.

Как раз ты пытаешься опыт ФБ экстраполировать на всю индустрию. Увы никто, из тех кто будет читать этот форум, даже близко не подойдет к таким масштабам.

G>>В остальных случаях сложность оптимизации на C++ и C# (и иногда Java) сравнимы, а учитывая в общем более высокую сложность разработки на C++ еще непонятно что будет проще в итоге.

EP>Нет, не сравнимы. В C++ я могу сделать много уровней абстракций, которые будут либо бесплатными, либо крайне дешёвыми. В C#, а тем более Java, так не получится. И вот за счёт этого получается проще.
А не делать уровни абстракции не? Или ты считаешь, что это на порядок сложнее?

EP>Мой поинт наоборот противоположный, и я уже устал его повторять:

EP>Предел оптимизации везде примерно одинаковый, разница в десятки процентов это не так уж серьёзно. Но на C++ этот предел гораздо проще достичь.
На практике ровно наоборот. В C++ можно вовсе не выделять память под объекты, а в C#\Java без этого никак. В некоторых случаях только один этот факт позволяет из кода на C++ выжать в разы больше быстродействия. Правда затраты на такую оптимизацию очень быстро превышают разумные пределы. Но для ФБ такие оптимизации оправданы, а для других — вовсе нет.
Re[34]: C# - from indians by indians
От: Evgeny.Panasyuk Россия  
Дата: 06.06.15 16:54
Оценка:
Здравствуйте, gandjustas, Вы писали:

EP>>Тезис в цитате (с которым я полностью согласен) довольно прост — на C++ проще создать быстрый код. Ты же пытаешься передёрнуть в какую-то совершенно другую плоскость

G>Плоскость та же самая. Просто ответь на вопрос насколько проще

Намного проще.

G>и насколько нужна скорость с учетом всех факторов,


Где-то нужна, а где-то нет

G>>>Для большинства проектов проценты прироста быстродействия

EP>>Причём тут "проценты"?
EP>>Выше как раз показано что при использовании Java-style это не проценты, а разы, и даже порядки.
G>А при использовании C# не разы.

В разы, бывает и на порядки

G>Кроме того операции с complex не такой уж частый случай. Я вот сомневаюсь что в том же ФБ много кода, работающего с вещественными числами.


Повторюсь в N-ый раз Это бьёт далеко не только по арифметике и подобным вычислениям.

G>>>останутся незамеченными и дешевле будет сделать апгрейд железа, чем заниматься оптимизацией. Поэтому утверждение что "на C++ быстрый код получить на порядки проще" не имеет никакого смысла и верно только в контексте фейсбука\гугла и еще пары-тройки гигантов.

EP>>Ты почему-то говоришь в контексте каких-то отдельных областей типа web'а — причём так, что как-будто ничего другого нет. Уж поверь "быстрый код на C++" нужен не только гигантам.
G>Не видел ни одного случая, чтобы без C++ нельзя было добиться достаточного быстродействия.

Опять 25. Без C++, на Java и C# можно добиться быстродействия, что не ясно-то? Ты с чем споришь?

EP>>Тебе попадаются задачи где не нужен? Поздравляю, вот только не надо необоснованно экстраполировать свой опыт на всю индустрию.

G>Как раз ты пытаешься опыт ФБ экстраполировать на всю индустрию.

Где я это пытаюсь делать?

G>Увы никто, из тех кто будет читать этот форум, даже близко не подойдет к таким масштабам.


Да причём тут вообще масштабы? Есть много программ которые работают на устройствах конечных пользователей и где нужна скорость.
Ты же пытаешься всё свести к каким-то случаям типа веб-масштабирования. Не хватает только коронного "всё в базу упирается".

G>>>В остальных случаях сложность оптимизации на C++ и C# (и иногда Java) сравнимы, а учитывая в общем более высокую сложность разработки на C++ еще непонятно что будет проще в итоге.

EP>>Нет, не сравнимы. В C++ я могу сделать много уровней абстракций, которые будут либо бесплатными, либо крайне дешёвыми. В C#, а тем более Java, так не получится. И вот за счёт этого получается проще.
G>А не делать уровни абстракции не? Или ты считаешь, что это на порядок сложнее?

Да, это на порядок сложнее. Например примеры из этого топика:
Вместо того чтобы просто объявить класс Complex — будешь вручную нарезать массив double.
Вместо того чтобы взять готовую ФВП transform, и передать в неё лямбду — будешь выписывать ручной for-цикл.
И чем больше уровней, тем больше ad-hoc boilerplate, причём комбинаторно.

EP>>Мой поинт наоборот противоположный, и я уже устал его повторять:

EP>>Предел оптимизации везде примерно одинаковый, разница в десятки процентов это не так уж серьёзно. Но на C++ этот предел гораздо проще достичь.
G>На практике ровно наоборот.

Почему это? Вот в этом топике и Java и C# показали скорость близкую к C++.

G>В C++ можно вовсе не выделять память под объекты, а в C#\Java без этого никак. В некоторых случаях только один этот факт позволяет из кода на C++ выжать в разы больше быстродействия. Правда затраты на такую оптимизацию очень быстро превышают разумные пределы.


Ты как раз подтверждаешь мои слова выше. Ты читал на что отвечаешь?

EP>>Предел оптимизации везде примерно одинаковый, разница в десятки процентов это не так уж серьёзно. Но на C++ этот предел гораздо проще достичь.
G>На практике ровно наоборот.

Re[24]: C# - from indians by indians
От: Evgeny.Panasyuk Россия  
Дата: 06.06.15 18:21
Оценка: 2 (2)
Здравствуйте, Sinix, Вы писали:

S>У меня соотношение 58ms/116ms в пользу x86.


S>UPD2. Тот же код с классами вместо структур:

S>
S>.NET Elapsed: 4723,0000 ms
S>


Здравствуйте, mik1, Вы писали:

M>Ты уверен, что в шарпе ты с бубном танцевал меньше, чем я в Яве?

M>Кстати, в Яве объекты дают только 3.5х просадку (~185мс против 58 мс) в отличии от полного ужоса шарпа (~4700 мс против 110 мс).


C++ версия
Автор: Evgeny.Panasyuk
Дата: 02.06.15
скомпилированная в JavaScript и запущенная в Firefox:

Elapsed = 0.0960432s


UPD: Иногда бывает даже вот так:

Elapsed = 0.0744424s

Отредактировано 06.06.2015 18:37 Evgeny.Panasyuk . Предыдущая версия . Еще …
Отредактировано 06.06.2015 18:22 Evgeny.Panasyuk . Предыдущая версия .
Re[25]: C# - from indians by indians
От: Evgeny.Panasyuk Россия  
Дата: 06.06.15 20:08
Оценка:
EP>C++ версия
Автор: Evgeny.Panasyuk
Дата: 02.06.15
скомпилированная в JavaScript и запущенная в Firefox:

EP>

EP>Elapsed = 0.0960432s

EP>
EP>UPD: Иногда бывает даже вот так:
EP>

EP>Elapsed = 0.0744424s


Исходный main:
int main()
{
    constexpr auto N = 1u << 24;
    vector<Complex> v, u;
    v.reserve(N);
    generate_n(back_inserter(v), N, random_complex);
    u = v;
    random_shuffle(begin(v), end(v));
    random_shuffle(begin(u), end(u));

    benchmark([&]
    {
        transform(begin(v), end(v), begin(u), begin(v), [](auto x, auto y) { return x*y; });
    });

    volatile auto anti_opti = accumulate(begin(v), end(v), Complex{});
    (void)anti_opti;
}

А вот main из .js отформатированный сторонней утилитой. Имена идентификаторов это то что я разревёрсил, до этого были одно-двух буквенные:
  JS
function main() {
    var a = 0,
        b = 0,
        c = 0,
        d = 0,
        e = 0,
        f = 0,
        g = 0,
        h = 0,
        i = 0,
        j = 0,
        l = 0,
        m = 0,
        n = 0,
        o = 0,
        q = 0,
        s = 0,
        t = 0.0,
        u = 0.0,
        v = 0.0,
        w = 0.0;
    s = r;
    r = r + 80 | 0;
    j = s + 16 | 0;
    i = s;
    l = s + 8 | 0;
    o = s + 48 | 0;
    m = s + 60 | 0;
    c = s + 36 | 0;
    d = s + 40 | 0;
    f = s + 44 | 0;
    g = s + 32 | 0;
    mem_as_Int32[o >> 2] = 0;
    q = o + 4 | 0;
    mem_as_Int32[q >> 2] = 0;
    h = o + 8 | 0;
    mem_as_Int32[h >> 2] = 0;
    mem_as_Int32[m >> 2] = 0;
    n = m + 4 | 0;
    mem_as_Int32[n >> 2] = 0;
    mem_as_Int32[m + 8 >> 2] = 0;
    e = Pn(268435456) | 0;
    mem_as_Int32[o >> 2] = e;
    mem_as_Int32[q >> 2] = e;
    mem_as_Int32[h >> 2] = e + 268435456;
    e = j + 8 | 0;
    b = 16777216;
    do {
        t = +(rand() | 0) / 1.0e3 + -1.0e3;
        mem_as_Float64[j >> 3] = t;
        t = +(rand() | 0) / 1.0e3 + -1.0e3;
        mem_as_Float64[e >> 3] = t;
        a = mem_as_Int32[q >> 2] | 0;
        if (a >>> 0 < (mem_as_Int32[h >> 2] | 0) >>> 0) {
            if (!a) a = 0;
            else {
                mem_as_Int32[a + 0 >> 2] = mem_as_Int32[j + 0 >> 2];
                mem_as_Int32[a + 4 >> 2] = mem_as_Int32[j + 4 >> 2];
                mem_as_Int32[a + 8 >> 2] = mem_as_Int32[j + 8 >> 2];
                mem_as_Int32[a + 12 >> 2] = mem_as_Int32[j + 12 >> 2]
            }
            mem_as_Int32[q >> 2] = a + 16
        } else Dc(o, j);
        b = b + -1 | 0
    } while ((b | 0) != 0);
    Cc(m, mem_as_Int32[o >> 2] | 0, mem_as_Int32[q >> 2] | 0);
    mem_as_Int32[c >> 2] = mem_as_Int32[o >> 2];
    mem_as_Int32[d >> 2] = mem_as_Int32[q >> 2];
    mem_as_Int32[i + 0 >> 2] = mem_as_Int32[c + 0 >> 2];
    mem_as_Int32[j + 0 >> 2] = mem_as_Int32[d + 0 >> 2];
    random_shuffle(i, j);
    mem_as_Int32[f >> 2] = mem_as_Int32[m >> 2];
    mem_as_Int32[g >> 2] = mem_as_Int32[n >> 2];
    mem_as_Int32[i + 0 >> 2] = mem_as_Int32[f + 0 >> 2];
    mem_as_Int32[j + 0 >> 2] = mem_as_Int32[g + 0 >> 2];
    random_shuffle(i, j);
    high_resolution_clock::now(i);
    a = mem_as_Int32[o >> 2] | 0;
    c = mem_as_Int32[q >> 2] | 0;
    if ((a | 0) != (c | 0)) {
        b = mem_as_Int32[m >> 2] | 0;
        while (1) {
            u = +mem_as_Float64[a >> 3];
            g = a + 8 | 0;
            w = +mem_as_Float64[g >> 3];
            v = +mem_as_Float64[b >> 3];
            t = +mem_as_Float64[b + 8 >> 3];
            mem_as_Float64[a >> 3] = u * v - w * t;
            mem_as_Float64[g >> 3] = w * v + u * t;
            a = a + 16 | 0;
            if ((a | 0) == (c | 0)) break;
            else b = b + 16 | 0
        }
    }
    high_resolution_clock::now(l);
    e = l;
    f = mem_as_Int32[e >> 2] | 0;
    e = mem_as_Int32[e + 4 >> 2] | 0;
    a = i;
    g = mem_as_Int32[a >> 2] | 0;
    a = mem_as_Int32[a + 4 >> 2] | 0;
    l = zc(2664, 8, 10) | 0;
    a = xp(f | 0, e | 0, g | 0, a | 0) | 0;
    a = zc(Le(l, (+(a >>> 0) + 4294967296.0 * +(P | 0)) / 1.0e9) | 0, 24, 1) | 0;
    Ld(j, a + (mem_as_Int32[(mem_as_Int32[a >> 2] | 0) + -12 >> 2] | 0) | 0);
    l = kj(j, 7520) | 0;
    l = mc[mem_as_Int32[(mem_as_Int32[l >> 2] | 0) + 28 >> 2] & 15](l, 10) | 0;
    ij(j);
    Me(a, l) | 0;
    we(a) | 0;
    a = mem_as_Int32[m >> 2] | 0;
    if (!a) a = mem_as_Int32[o >> 2] | 0;
    else {
        b = mem_as_Int32[n >> 2] | 0;
        if ((b | 0) != (a | 0)) mem_as_Int32[n >> 2] = b + (~((b + -16 - a | 0) >>> 4) << 4);
        Qn(a);
        a = mem_as_Int32[o >> 2] | 0
    }
    if (!a) {
        r = s;
        return 0
    }
    b = mem_as_Int32[q >> 2] | 0;
    if ((b | 0) != (a | 0)) mem_as_Int32[q >> 2] = b + (~((b + -16 - a | 0) >>> 4) << 4);
    Qn(a);
    r = s;
    return 0
}
mem_as_Int32 и mem_as_Float64 это views одного и того же буфера (есть views и других типов). Heap и stack находятся в этом буфере.

Первый цикл это generate_n:
e = j + 8 | 0;
b = 16777216;
do {
    t = +(rand() | 0) / 1.0e3 + -1.0e3;
    mem_as_Float64[j >> 3] = t;
    t = +(rand() | 0) / 1.0e3 + -1.0e3;
    mem_as_Float64[e >> 3] = t;
    a = mem_as_Int32[q >> 2] | 0;
    if (a >>> 0 < (mem_as_Int32[h >> 2] | 0) >>> 0) {
        if (!a) a = 0;
        else {
            mem_as_Int32[a + 0 >> 2] = mem_as_Int32[j + 0 >> 2];
            mem_as_Int32[a + 4 >> 2] = mem_as_Int32[j + 4 >> 2];
            mem_as_Int32[a + 8 >> 2] = mem_as_Int32[j + 8 >> 2];
            mem_as_Int32[a + 12 >> 2] = mem_as_Int32[j + 12 >> 2]
        }
        mem_as_Int32[q >> 2] = a + 16
    } else Dc(o, j);
    b = b + -1 | 0
} while ((b | 0) != 0);


Следующий цикл это transform с легко узнаваемой формулой умножения комплексных чисел:
high_resolution_clock::now(i);
a = mem_as_Int32[o >> 2] | 0;
c = mem_as_Int32[q >> 2] | 0;
if ((a | 0) != (c | 0)) {
    b = mem_as_Int32[m >> 2] | 0;
    while (1) {
        u = +mem_as_Float64[a >> 3];
        g = a + 8 | 0;
        w = +mem_as_Float64[g >> 3];
        v = +mem_as_Float64[b >> 3];
        t = +mem_as_Float64[b + 8 >> 3];
        mem_as_Float64[a >> 3] = u * v - w * t;
        mem_as_Float64[g >> 3] = w * v + u * t;
        a = a + 16 | 0;
        if ((a | 0) == (c | 0)) break;
        else b = b + 16 | 0
    }
}
high_resolution_clock::now(l);
То есть это результат компиляции:
transform(begin(v), end(v), begin(u), begin(v), [](auto x, auto y) { return x*y; });

Несмотря на volatile, компилятор выкинул accumulate. Его можно принудительно добавить (через вывод в результата в cout), но на замер времени это не повлияло.

P.S. Думаю на базе Emscripten можно сделать компилятор из C++ в Java — тогда там наконец "появятся" автоматические структуры

UPD: у компилятора есть опция выводить не "сжатый" код:
  main js
function _main() {
 var $$01$i = 0, $$byval_copy2 = 0, $$byval_copy3 = 0, $0 = 0, $1 = 0, $10 = 0, $14 = 0.0, $18 = 0.0, $19 = 0, $2 = 0, $24 = 0, $3 = 0, $34 = 0.0, $35 = 0, $36 = 0.0, $37 = 0.0, $39 = 0.0, $4 = 0, $49 = 0, $5 = 0, $51 = 0, $54 = 0, $55 = 0, $57 = 0, $6 = 0, $60 = 0, $61 = 0, $62 = 0, $67 = 0, $72 = 0, $76 = 0, $78 = 0, $8 = 0, $80 = 0, $86 = 0, $88 = 0, $__first1$01015$i$i$i = 0, $__first2$01114$i$i$i = 0, $end$i = 0, $f$idx$val$idx$val$i = 0, $f$idx$val$idx2$val$i = 0, $u = 0, $v = 0, sp = 0;
 sp = STACKTOP;
 STACKTOP = STACKTOP + 80 | 0;
 $$byval_copy3 = sp + 16 | 0;
 $$byval_copy2 = sp;
 $end$i = sp + 8 | 0;
 $v = sp + 48 | 0;
 $u = sp + 60 | 0;
 $0 = sp + 36 | 0;
 $1 = sp + 40 | 0;
 $2 = sp + 44 | 0;
 $3 = sp + 32 | 0;
 HEAP32[$v >> 2] = 0;
 $4 = $v + 4 | 0;
 HEAP32[$4 >> 2] = 0;
 $5 = $v + 8 | 0;
 HEAP32[$5 >> 2] = 0;
 HEAP32[$u >> 2] = 0;
 $6 = $u + 4 | 0;
 HEAP32[$6 >> 2] = 0;
 HEAP32[$u + 8 >> 2] = 0;
 $8 = __Znwj(268435456) | 0;
 HEAP32[$v >> 2] = $8;
 HEAP32[$4 >> 2] = $8;
 HEAP32[$5 >> 2] = $8 + 268435456;
 $10 = $$byval_copy3 + 8 | 0;
 $$01$i = 16777216;
 do {
  $14 = +(_rand() | 0) / 1.0e3 + -1.0e3;
  HEAPF64[$$byval_copy3 >> 3] = $14;
  $18 = +(_rand() | 0) / 1.0e3 + -1.0e3;
  HEAPF64[$10 >> 3] = $18;
  $19 = HEAP32[$4 >> 2] | 0;
  if ($19 >>> 0 < (HEAP32[$5 >> 2] | 0) >>> 0) {
   if (!$19) $24 = 0; else {
    HEAP32[$19 + 0 >> 2] = HEAP32[$$byval_copy3 + 0 >> 2];
    HEAP32[$19 + 4 >> 2] = HEAP32[$$byval_copy3 + 4 >> 2];
    HEAP32[$19 + 8 >> 2] = HEAP32[$$byval_copy3 + 8 >> 2];
    HEAP32[$19 + 12 >> 2] = HEAP32[$$byval_copy3 + 12 >> 2];
    $24 = $19;
   }
   HEAP32[$4 >> 2] = $24 + 16;
  } else __ZNSt3__16vectorI7ComplexNS_9allocatorIS1_EEE21__push_back_slow_pathIS1_EEvOT_($v, $$byval_copy3);
  $$01$i = $$01$i + -1 | 0;
 } while (($$01$i | 0) != 0);
 __ZNSt3__16vectorI7ComplexNS_9allocatorIS1_EEE6assignIPS1_EENS_9enable_ifIXaasr21__is_forward_iteratorIT_EE5valuesr16is_constructibleIS1_NS_15iterator_traitsIS8_E9referenceEEE5valueEvE4typeES8_S8_($u, HEAP32[$v >> 2] | 0, HEAP32[$4 >> 2] | 0);
 HEAP32[$0 >> 2] = HEAP32[$v >> 2];
 HEAP32[$1 >> 2] = HEAP32[$4 >> 2];
 HEAP32[$$byval_copy2 + 0 >> 2] = HEAP32[$0 + 0 >> 2];
 HEAP32[$$byval_copy3 + 0 >> 2] = HEAP32[$1 + 0 >> 2];
 __ZNSt3__114random_shuffleINS_11__wrap_iterIP7ComplexEEEEvT_S5_($$byval_copy2, $$byval_copy3);
 HEAP32[$2 >> 2] = HEAP32[$u >> 2];
 HEAP32[$3 >> 2] = HEAP32[$6 >> 2];
 HEAP32[$$byval_copy2 + 0 >> 2] = HEAP32[$2 + 0 >> 2];
 HEAP32[$$byval_copy3 + 0 >> 2] = HEAP32[$3 + 0 >> 2];
 __ZNSt3__114random_shuffleINS_11__wrap_iterIP7ComplexEEEEvT_S5_($$byval_copy2, $$byval_copy3);
 __ZNSt3__16chrono12steady_clock3nowEv($$byval_copy2);
 $f$idx$val$idx$val$i = HEAP32[$v >> 2] | 0;
 $f$idx$val$idx2$val$i = HEAP32[$4 >> 2] | 0;
 if (($f$idx$val$idx$val$i | 0) != ($f$idx$val$idx2$val$i | 0)) {
  $__first1$01015$i$i$i = $f$idx$val$idx$val$i;
  $__first2$01114$i$i$i = HEAP32[$u >> 2] | 0;
  while (1) {
   $34 = +HEAPF64[$__first1$01015$i$i$i >> 3];
   $35 = $__first1$01015$i$i$i + 8 | 0;
   $36 = +HEAPF64[$35 >> 3];
   $37 = +HEAPF64[$__first2$01114$i$i$i >> 3];
   $39 = +HEAPF64[$__first2$01114$i$i$i + 8 >> 3];
   HEAPF64[$__first1$01015$i$i$i >> 3] = $34 * $37 - $36 * $39;
   HEAPF64[$35 >> 3] = $36 * $37 + $34 * $39;
   $__first1$01015$i$i$i = $__first1$01015$i$i$i + 16 | 0;
   if (($__first1$01015$i$i$i | 0) == ($f$idx$val$idx2$val$i | 0)) break; else $__first2$01114$i$i$i = $__first2$01114$i$i$i + 16 | 0;
  }
 }
 __ZNSt3__16chrono12steady_clock3nowEv($end$i);
 $49 = $end$i;
 $51 = HEAP32[$49 >> 2] | 0;
 $54 = HEAP32[$49 + 4 >> 2] | 0;
 $55 = $$byval_copy2;
 $57 = HEAP32[$55 >> 2] | 0;
 $60 = HEAP32[$55 + 4 >> 2] | 0;
 $61 = __ZNSt3__124__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_j(2664, 8, 10) | 0;
 $62 = _i64Subtract($51 | 0, $54 | 0, $57 | 0, $60 | 0) | 0;
 $67 = __ZNSt3__124__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_j(__ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEElsEd($61, (+($62 >>> 0) + 4294967296.0 * +(tempRet0 | 0)) / 1.0e9) | 0, 24, 1) | 0;
 __ZNKSt3__18ios_base6getlocEv($$byval_copy3, $67 + (HEAP32[(HEAP32[$67 >> 2] | 0) + -12 >> 2] | 0) | 0);
 $72 = __ZNKSt3__16locale9use_facetERNS0_2idE($$byval_copy3, 7520) | 0;
 $76 = FUNCTION_TABLE_iii[HEAP32[(HEAP32[$72 >> 2] | 0) + 28 >> 2] & 15]($72, 10) | 0;
 __ZNSt3__16localeD2Ev($$byval_copy3);
 __ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE3putEc($67, $76) | 0;
 __ZNSt3__113basic_ostreamIcNS_11char_traitsIcEEE5flushEv($67) | 0;
 $78 = HEAP32[$u >> 2] | 0;
 if (!$78) $86 = HEAP32[$v >> 2] | 0; else {
  $80 = HEAP32[$6 >> 2] | 0;
  if (($80 | 0) != ($78 | 0)) HEAP32[$6 >> 2] = $80 + (~(($80 + -16 - $78 | 0) >>> 4) << 4);
  __ZdlPv($78);
  $86 = HEAP32[$v >> 2] | 0;
 }
 if (!$86) {
  STACKTOP = sp;
  return 0;
 }
 $88 = HEAP32[$4 >> 2] | 0;
 if (($88 | 0) != ($86 | 0)) HEAP32[$4 >> 2] = $88 + (~(($88 + -16 - $86 | 0) >>> 4) << 4);
 __ZdlPv($86);
 STACKTOP = sp;
 return 0;
}
Отредактировано 07.06.2015 9:30 Evgeny.Panasyuk . Предыдущая версия . Еще …
Отредактировано 06.06.2015 21:53 Evgeny.Panasyuk . Предыдущая версия .
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.