Здравствуйте, Evgeny.Panasyuk, Вы писали:
M>>Да, кстати буст хорошо бы убрать из примера (как обещано).
g++ 4.9.2 под cygwin не хочет компилить с командной строкой с Coliru. std=c++14 распознает.
Все 3 ошибки идентичные — на создание объектов:
main.cpp: In function 'Complex operator+(Complex, Complex)':
main.cpp:17:37: error: could not convert '{(x.Complex::re + y.Complex::re), (x.Complex::im + y.Complex::im)}' from '<brace-enclosed initializer list>' to 'Complex'
return {x.re + y.re, x.im + y.im};
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, MT-Wizard, Вы писали:
MW>>Просто прекрасный пример MW>>Только что полазил по отчётам производительности — лучшее что там есть это на 14% медленнее старого компилера (который и не трогают давно) на одном конкретном тесте. Пустите столько же ресурсов в него — и шарп его не догонит ещё лет 200
S>Они закрытые вроде были, тынц. Что-то поменялось?
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Да, там конечно же всё хорошо заинлайнится, и не будет уступать "ручной" версии.
EP>Кстати, библиотека типа Eigen реализует дополнительные оптимизации — например конструкция вида EP>
EP>Vector result = v1 * v2 * v3 * v4;
EP>
Развернётся в один цикл сразу по всем векторам.
Ну вот фишка-то как раз в том, что в С++ у меня развязаны руки.
Я могу натравить профайлер на моё приложение, посмотреть, где теряется время, и переделать оператор умножения векторов так, чтобы он возвращал deferredMultiplication<T>, а реальные умножения/сложения выполнял при конверсии в Vector. Потом повторно натравить профайлер и посмотреть, не испортило ли это локальность кэшей — и так по кругу, пока не получу нужную производительность.
При этом в самом коде вычисления result = v1 * v2 * v3 * v4 у меня не будет ни следа этих оптимизаций; т.е. я не ломаю корректную программу, и она остаётся читаемой даже после пяти циклов оптимизации.
EP>Это может ухудшить показатели Java кода в разы, так как по умолчанию compacting GC выделяет память последовательно. Перемешав указатели в массиве — уже не получится последовательный обход памяти.
Нам обещали работу с byte[] через misc.Unsafe, чтобы избежать boxing penalty. Я уже запасся попкорном и орешками, т.к. раньше такого не видел.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, mik1, Вы писали:
EP>>Здесь используется не класс типа Complex, а класс типа ComplexArray. EP>>Собственно об этом и была речь — простейшая абстракция Complex не совместима с производительностью. То есть нельзя просто отдельно создать класс Complex и положить его в отдельный стандартный массив, в стандартную deque, в стандартную priority_queue и т.п. — их приходится вручную скрещивать. M>А вот тут ты немного обманываешься — ни в деке, ни в очереди ты уже безразрывный блок памяти не получишь, и весь твой выигрыш рискует превратиться в тыкву
Реализации std::deque внутри используют непрерывные chunk'и. std::priority_queue по-умолчанию хранит все элементы в одном vector.
Да даже если взять node-based структуру данных — в Java в каждом узле будет хранится не элемент, а указатель, а это лишняя индерекция, что бьёт по производительности — в общем случае вместо одного cache miss'а будет два.
EP>>Причём если взять структуру чуть-чуть посложнее, типа {double, float, int} — то всё, приплыли капитально. M>Давай по честному — мой код по длине не сильно больше твоего.
Вот только делает он не то что было запрошено — ComplexArray вместо Complex, со всеми вытекающими отсюда следствиями: в другую структуру данных комплексное число не положить, передать в функцию/использовать внутри несколько отдельных Complex чисел не получится, со сторонними алгоритмами типа std::inner_product — это не работает.
M>По производительности подозреваю что тоже похож.
Так я сразу сказал:
EP>P.S. На Java можно писать быстрый код, но если выходить за рамки каких-то примитивнейших случаев (типа сортировки массива int'ов) — то приходится работать против языка, а не вместе с ним — нужно отказываться от GC и даже классов, и нарезать структуры вручную по массивам байт — по сути это уровень даже ниже чем в языке C.
По факту так и получилось — ниже чем в C, так как даже там можно сделать массив complex без ручной нарезки.
M>По сложности — тоже самое.
Нет. Вот это:
M> return ar[ i * 2 + 1 ];
M> ...
M> ar[i * 2+1] = v;
M> ...
M> private double[] u_ar = new double[ N * 2 ];
M> ...
M> for ( int i = 0; i < u_ar.length / 2; ++i ) {
M> v.re(i, u.re(i) * v.re(i) - u.im(i) * v.im(i) );
M> v.im(i, u.re(i)*v.im(i) + u.im(i)*v.re(i));
M> }
Сложнее чем описание того как работает одно комплексное число.
M>Синклер тут где-то заявлял, что такое в принципе невозможно.
ЕМНИП он другое заявлял. Тем не менее, у тебя не реализовано даже что-то отдалённо напоминающее отдельное комплексное число.
M>Просто поверь, что более сложную логику я точно также напишу (но за деньги ).
Верю. Повторюсь — на Java можно писать быстрый код. Но этот код будет на порядке сложнее чем например на C++, а иногда даже чем C.
M>Да, и мне казалось в числодробилках обычно довольно однородные типы данных обрабатываются.
Я уже выше по теме говорил что проблема с отсутствием struct бьёт далеко не только по число-дробилкам. Например банальная сортировка небольших структур также будет тормозить, не говоря уже о том что результат не будет последовательным по памяти.
Правильный доступ к памяти, мало число индерекций — это ключ к быстрому коду (конечно после алгоритмических оптимизаций).
EP>>В этом примере (перемножение массивов объектов Complex) — тормоза на Java будут даже без учёта GC. M>"Тормоза" тут будут только от 12-16 байтов заголовка объекта в Яве,
Нет, тормоза будут далеко не только от этого.
M>которые будут "разрывать" последовательность даблов.
А она разорвётся от первого перетасовывания/сортировки, причём конкретно — я же там random_shuffle поставил.
M>Как только ты уйдешь от массивов в плюсах, все станет на свои места.
Если писать на C++ в Java-style, хранить элементы всех массивов по указателям, добавлять каждый под-объект в класс по указателю — то да, тормоз будет конкретный.
M>Кроме того, как я уже намекнул, твой пример скромно обходит любые выделения памяти
Здравствуйте, mik1, Вы писали:
M>>>Да, кстати буст хорошо бы убрать из примера (как обещано). M>g++ 4.9.2 под cygwin не хочет компилить с командной строкой с Coliru. std=c++14 распознает. M>Все 3 ошибки идентичные — на создание объектов:
На Coliru версия новее. Нужно добавить ручной конструктор в Complex:
Complex(double re = 0., double im = 0.) : re(re), im(im) {}
Здравствуйте, mik1, Вы писали:
M>Давай пока что так, требует JMH, которому я доверяю тестировать производительность:
Ну, во-первых, у вас в коде ошибка. Умножение реализовано неправильно.
Попробуйте скормить туда два массива по одному элементу, проинициализированному в i ( {0, 1}).
Это как раз иллюстрирует сложность явы для вычислительных задач — вы не можете написать оператор умножения векторов, построенный на умножении скаляров.
Вам придётся руками выписывать все операции типа вектор*вектор, вектор*скаляр; скаляр*скаляр — с утроенным риском напороть в одной из реализаций.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, gandjustas, Вы писали:
G>Мало того что const нифига не помог
const_cast<> как раз можно отследить глобальным поиском, так же как reinterpret_cast<>...
гораздо печальнее, что оставили приведение типов в синтаксисе Си, что позволит перехитрить такие проверки исходников.
G>так еще и утечку памяти создал.
Ну это как раз нормально. Утечку можно и в C# создать. Утечка — это всегда признак непродуманности способа владения.
Здравствуйте, Aртём, Вы писали:
EP>>Ок, другой пример — глобальные объекты для многих проектов это "бэд практис", для некоторых же это вполне стандартное решение — типа микроконтроллеров Aё>Вы в курсе, что под микроконтроллеры нету C++?
Я в курсе что есть.
EP>>А где переход на личности? Ты ведь действительно не знаешь что там внутри происходит, разве нет? При этом делаешь какие-то нелепые попытки придраться. Aё>Я уже Вам 3 раза повторил, что удобный доступ к памяти из C++ — для вычислений не значит ничего, ибо Ваш код C++ тормозной по сравнению с специализированными библиотеками.
Для полного фарша тебе осталось только сказать коронное "всё в базу упирается"
Aё>При этом Ваш код неустойчив, а на вопрос "как записать ошибку и тректрейс в лог", Вы предлагаете убивать программу.
Я предлагаю убивать программу в случае если порушены инварианты или пред/пост-условия — так как она находится в неизвестном состоянии, и неизвестно как туда попала.
EP>>Даже если и больше по продолжительности, то по качеству — судя по всему нет Aё>99/100 в IKM в 2011г- но без фич C++'11.
Тест — да, это сильное подтверждение качества опыта.
EP>>Что не понятно? Распараллеливание даст больший эффект нежели векторизация. Aё>Почитайте про цену синхронизации. Узнайте много нового .
Не путай concurrent и parallel programming — в последнем синхронизации на порядки меньше.
Конкретно между потоками parallel_transform (который применим в данном случае) вообще никакой синхронизации нет, разве что false-sharing на границах — вся синхронизация это отправка задачи в pool, и ожидание результата — всё
EP>>>>Да даже если в Java-версии с Complex объектами будет векторизация, она всё равно будет медленнее C++ версии без векторизации — из-за плохого паттерна доступа к памяти — сути примера это никак не поменяет. Aё>>>Вы так ничего и не поняли. EP>>Куда уж там. Aё>Попробую объяснить — сделайте N-мерный массив, сделайте обёртку с доступом по смешению через direct ByteBuffer- и будет счастье.
Код в студию.
Aё>>>А ведь я указывал парой сообщений выше- что Python с NumPy порвёт ваш плюснутый код, как тузик грелку. EP>>По какому критерию? Aё>По скорости
Аргументы?
Aё>и выразительности.
Конкретнее.
Aё>>>Потому что узкие места ускоряются через использование заточенной библиотеки. EP>>Которая далеко не всегда существует. Aё>Не тешьте себя иллюзиями- всё украли до нас, причём ещё во времена Фортрана.
Это невозможно в принципе.
Aё>>>А вот в качестве "клея" С++ — далеко не лучший вариант, EP>>Аргументы? Aё>Я привёл Вам аргумент- неустойчивый код, отсутствие логирования стек трейсов,
Я же сказал что stacktrace есть, просто не стандартный
Aё>фрагментация кучи.
1. У GC обычно есть специальная куча для больших объектов, которая не сжимается, потому что дорого — в итоге получается та же самая фрагментация. То есть у любого GC здесь tradeoff — либо перемещать огромные объекты, либо получать ту же фрагментацию.
2. Если эффекты фрагментации важны — на C++ без всяких проблем используются специальные аллокаторы/pool'ы.
Aё>Вам мало? Ну добавить ещё киллер-фичу перегрузка оператора aka выстрелить себе в ногу. В код выглядит выразительным и коротким, но программист на самом деле не знает, как оно под капотом работает. И не понимает, что не знает.
И какая тут разница с явным методом, в этом аспекте?
Aё>>>>>и размер кода для попадания в кэш CPU почему-то знатоки C++ не упомянули, EP>>>>А зачем его упоминать? Думаешь код перемножения массивов не уместится в intruction cache? Aё>>>Думаю, что реальные задачи сложнее Вашего примера, а шаблоны C++ имеют дурную репутацию разбухания кода. EP>>В реальных задачах там где нужно используется динамический полиморфизм вместо статического, причём обычно где-то наверху. Это на порядки проще чем "работа вопреки языку" (как в тех случаях когда нужна скорость на Java). Aё>Кажется, кто-то ставил Java в вину отсутствие статического полиморфизма- и тут же готов в реальных задачах от него отказаться.
Это демагогия. Внизу остаётся тот же статический полиморфизм.
Aё>Вот и C++ "где-то наверху" не нужен. А "где-то внизу" он тоже не нужен, ибо есть библиотеки на C, где авторы в курсе про векторные расширения, кэш процессора, и т.д..
На C быстрый код писать намного труднее чем на C++ — как раз из-за отсутствия нормального статического полиморфизма. Посмотри хотя бы на GLib — там сплошное type-erasure.
EP>>Даже если допустить что это так — того факта что в Java нет структур, и связанными с этим тормозами или танцами с ручной нарезкой массивов байт на структуры, или факта того что в нагруженных приложениях частенько отказываются от GC — это никак не отменяет. Aё>Не отказываются от GC- а минимизируют освобождение памяти.
Именно что отказываются, гугли "java off heap".
Aё>Обратите внимание, это и программ на C++ касается (фрагментация кучи).
Правильная работа с памятью важна для скорости, и в C++ для этого есть естественные встроенные средства. В Java же приходится опускаться на уровень даже ниже чем C, нарезая вручную структуры, что кстати даже было продемонстрировано выше по топику.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
M>>А вот тут ты немного обманываешься — ни в деке, ни в очереди ты уже безразрывный блок памяти не получишь, и весь твой выигрыш рискует превратиться в тыкву
EP>Реализации std::deque внутри используют непрерывные chunk'и. std::priority_queue по-умолчанию хранит все элементы в одном vector.
То есть у дека вставка в середину будет иметь сложность с такой заметной константой??? (больше одного элемента двигать???)
Priority heap для value types будет иметь смысл только до определнных длин структур. После какого-то лимита копирование станет слишком дорогим.
EP>Да даже если взять node-based структуру данных — в Java в каждом узле будет хранится не элемент, а указатель, а это лишняя индерекция, что бьёт по производительности — в общем случае вместо одного cache miss'а будет два.
Причем тут Ява??? Пользуешься указателями в любом языке — будут указатели. Нет — не будут. Все это можно обойти при некоторм опыте в Яве.
EP>>>Причём если взять структуру чуть-чуть посложнее, типа {double, float, int} — то всё, приплыли капитально. M>>Давай по честному — мой код по длине не сильно больше твоего.
EP>Вот только делает он не то что было запрошено — ComplexArray вместо Complex, со всеми вытекающими отсюда следствиями: в другую структуру данных комплексное число не положить, передать в функцию/использовать внутри несколько отдельных Complex чисел не получится, со сторонними алгоритмами типа std::inner_product — это не работает.
Твой код перемножает вектора и мой код перемножает вектора. Размер и производительность похожи. Точка.
EP>Верю. Повторюсь — на Java можно писать быстрый код. Но этот код будет на порядке сложнее чем например на C++, а иногда даже чем C.
Ты мне так и не рассказал про кастомные аллокаторы, которыми славятся плюсы Меня в той же самой ситуации может и стандартный устроить (TLAB-ы в Яве весьма хорошо написаны).
А value types — да, на плюсах удобнее. На Яве — не велика проблема.
M>>Да, и мне казалось в числодробилках обычно довольно однородные типы данных обрабатываются.
EP>Я уже выше по теме говорил что проблема с отсутствием struct бьёт далеко не только по число-дробилкам. Например банальная сортировка небольших структур также будет тормозить, не говоря уже о том что результат не будет последовательным по памяти.
Ключевое слово — небольших. И второе ключевое слово, которое ты скромно упустил — фиксированной длины.
EP>Правильный доступ к памяти, мало число индерекций — это ключ к быстрому коду (конечно после алгоритмических оптимизаций).
Да кто бы спорил!
EP>>>В этом примере (перемножение массивов объектов Complex) — тормоза на Java будут даже без учёта GC. M>>"Тормоза" тут будут только от 12-16 байтов заголовка объекта в Яве,
EP>Нет, тормоза будут далеко не только от этого.
50 против 57 мс (твой и мой примеры)? Именно из-за этого (если GC за скобки вынести). С заголовками у меня 180-190 мс было
M>>которые будут "разрывать" последовательность даблов. EP>А она разорвётся от первого перетасовывания/сортировки, причём конкретно — я же там random_shuffle поставил.
Если сортировать объекты — само собой. Но ты ж не объекты сортировал? Таки зачем меня пытаешься убедить это делать?
M>>Как только ты уйдешь от массивов в плюсах, все станет на свои места.
EP>Если писать на C++ в Java-style, хранить элементы всех массивов по указателям, добавлять каждый под-объект в класс по указателю — то да, тормоз будет конкретный.
Ну давай, расскажи, как ты например со стрoками переменной длины будешь работать в виде value types?
Здравствуйте, mik1, Вы писали:
M>>>А вот тут ты немного обманываешься — ни в деке, ни в очереди ты уже безразрывный блок памяти не получишь, и весь твой выигрыш рискует превратиться в тыкву EP>>Реализации std::deque внутри используют непрерывные chunk'и. std::priority_queue по-умолчанию хранит все элементы в одном vector. M>То есть у дека вставка в середину будет иметь сложность с такой заметной константой??? (больше одного элемента двигать???)
Сложность вставки в середину std::deque — линейная.
M>Priority heap для value types будет иметь смысл только до определнных длин структур. После какого-то лимита копирование станет слишком дорогим.
1. Это никак не отменяет того факта что на Java придётся реализовывать для каждого типа такую структуру.
2. Value types они разные бывают, например может быть вот такой:
struct Foo
{
int priority;
vector<Bar> data;
};
sizeof такой структуры небольшой, при использовании priority_queue<Foo> — приоритеты будут хранится "in-place", в аналоге же на Java появится лишняя индерекция.
EP>>Да даже если взять node-based структуру данных — в Java в каждом узле будет хранится не элемент, а указатель, а это лишняя индерекция, что бьёт по производительности — в общем случае вместо одного cache miss'а будет два. M>Причем тут Ява??? Пользуешься указателями в любом языке — будут указатели. Нет — не будут.
При том что она их навязывает там где их могло и не быть.
M>Все это можно обойти при некоторм опыте в Яве.
Конечно можно обойти, вручную нарезая структуры — я об этом сразу и сказал
EP>>>>Причём если взять структуру чуть-чуть посложнее, типа {double, float, int} — то всё, приплыли капитально. M>>>Давай по честному — мой код по длине не сильно больше твоего. EP>>Вот только делает он не то что было запрошено — ComplexArray вместо Complex, со всеми вытекающими отсюда следствиями: в другую структуру данных комплексное число не положить, передать в функцию/использовать внутри несколько отдельных Complex чисел не получится, со сторонними алгоритмами типа std::inner_product — это не работает. M>Твой код перемножает вектора и мой код перемножает вектора.
Напоминаю:
M>>Попутно хотелось бы определить, по каким критериям мы сравниваем.
EP>Простоту работы со struct-like вещами, а конкретнее — скорость выполнения и удобство кода.
Вместо работы со struct-like — ты показал неудобное error-prone ручное раскидывание полей на элементы массива.
M>Размер и производительность похожи. Точка.
Опять таки, то что на Java можно написать быстрый код дорогой ценной — я сказал в том же сообщении.
EP>P.S. На Java можно писать быстрый код, но если выходить за рамки каких-то примитивнейших случаев (типа сортировки массива int'ов) — то приходится работать против языка, а не вместе с ним — нужно отказываться от GC и даже классов, и нарезать структуры вручную по массивам байт — по сути это уровень даже ниже чем в языке C.
Ты продемонстрировал ровно то что я и сказал — нарезал массив на "виртуальные" структуры.
Про размер кода вообще смешно — с твоим подходом тебе придётся заново реализовывать каждую структуру данных, вместо пере-использования имеющихся. Да даже не то что структуру данных, а стоит мне добавить несколько вызовов методов vector'а — тебе придётся писать новые wrapper'ы.
Да даже в таком виде у тебя кода намного больше. Если же вычесть лишнее типа import'ов/include'ов и то что ты не реализовал (типа random_shuffle/accumulate/operator+) — то разница получится в разы
EP>>Верю. Повторюсь — на Java можно писать быстрый код. Но этот код будет на порядке сложнее чем например на C++, а иногда даже чем C. M>Ты мне так и не рассказал про кастомные аллокаторы, которыми славятся плюсы
Что конкретно тебя интересует?
И почему ты считаешь что это вообще относится к теме? Структуры есть даже в C#
M>>>Да, и мне казалось в числодробилках обычно довольно однородные типы данных обрабатываются. EP>>Я уже выше по теме говорил что проблема с отсутствием struct бьёт далеко не только по число-дробилкам. Например банальная сортировка небольших структур также будет тормозить, не говоря уже о том что результат не будет последовательным по памяти. M>Ключевое слово — небольших.
1. Поля используемые для сортировки могут быть в структуре, а payload — оставаться неподвижным в куче.
2. Бывает целесообразно сортировать даже большие структуры "inplace" — например если часто делается линейный обход.
M>И второе ключевое слово, которое ты скромно упустил — фиксированной длины.
Что конкретно имеешь в виду?
EP>>>>В этом примере (перемножение массивов объектов Complex) — тормоза на Java будут даже без учёта GC. M>>>"Тормоза" тут будут только от 12-16 байтов заголовка объекта в Яве, EP>>Нет, тормоза будут далеко не только от этого. M>50 против 57 мс (твой и мой примеры)? Именно из-за этого (если GC за скобки вынести). С заголовками у меня 180-190 мс было
Так ты же не показал массив структур complex ни в каком виде. Ты показал ComplexArray, то есть ту самую ручную нарезку — которая необходима для быстрого Java кода.
M>>>которые будут "разрывать" последовательность даблов. EP>>А она разорвётся от первого перетасовывания/сортировки, причём конкретно — я же там random_shuffle поставил. M>Если сортировать объекты — само собой. Но ты ж не объекты сортировал? Таки зачем меня пытаешься убедить это делать?
Я же говорю — у меня там random_shuffle который тасует элементы массива
M>>>Как только ты уйдешь от массивов в плюсах, все станет на свои места. EP>>Если писать на C++ в Java-style, хранить элементы всех массивов по указателям, добавлять каждый под-объект в класс по указателю — то да, тормоз будет конкретный. M>Ну давай, расскажи, как ты например со стрoками переменной длины будешь работать в виде value types?
Даже с обычными строками/контейнерами переменной длины получается вот какая штука: если в класс Foo добавить под-объект строку, то в случае Java в самом объекте будет хранится указатель на объект в котором хранится указатель на буфер. В C++ же будет указатель на буфер попадёт в сам объект класса Foo — уже на одну индерекцию меньше (не говоря уже об оптимизациях коротких строк в случае которых сам буфер будет внутри объекта класса Foo).
И вот эти лишние индерекции они повсюду, и выкорчевыватся они только трудоёмкими низкоуровневыми приёмами.
Здравствуйте, mik1, Вы писали:
M>50 против 57 мс (твой и мой примеры)? Именно из-за этого (если GC за скобки вынести). С заголовками у меня 180-190 мс было
Представь, что эта калькуляция повторяется 100500 тысяч раз. Для нашего продукта 14% это критично. Последнее ускорение, которое я делал, было на 5% и потратил на это 4 недели работы, как и было запланировано.
Получается, в этой конкретной задаче, Джава годится для новых числодробилок, где нельзя сравнить, или для терпеливых клиентов. По поводу бизнеса и денег, соглашусь, это вполне в духе современности, с удешевлением и снижением качества.
Здравствуйте, greenpci, Вы писали:
G>Представь, что эта калькуляция повторяется 100500 тысяч раз. Для нашего продукта 14% это критично.
Если писать код подобным образом на Java то и будет получаться скорость очень близкая к native'у.
Справедливости ради, разница в десятки процентов далеко не везде существенна, но тут дело в другом — во-первых код в таком стиле трудно писать (особенно когда нужны структуры вида {double, float, int}), во-вторых его нужно писать очень много, так как элементарная композиция не работает (нельзя взять отдельный массив и положить туда отдельный complex, и вызывать для него отдельный transfrom — всё это нужно сплавлять вместе вручную, и так каждую комбинацию).
А вот если писать в Java-стиле — то по всему коду появляются лишние уровни индеркции, лишние аллокации и т.п. — и вот тут отличие может быть не на десятки процентов, а в разы, на порядок, а в особо запущенных случаях на порядки.
Здравствуйте, greenpci, Вы писали:
G>Здравствуйте, mik1, Вы писали:
M>>50 против 57 мс (твой и мой примеры)? Именно из-за этого (если GC за скобки вынести). С заголовками у меня 180-190 мс было
G>Представь, что эта калькуляция повторяется 100500 тысяч раз. Для нашего продукта 14% это критично. Последнее ускорение, которое я делал, было на 5% и потратил на это 4 недели работы, как и было запланировано.
Меня больше пугают 30% вариативности результатов сишного примера. В Яве там практически нулевое стандартное отклонение.
Откуда оно берется в си — хз.
Здравствуйте, Sinclair, Вы писали:
EP>>Это может ухудшить показатели Java кода в разы, так как по умолчанию compacting GC выделяет память последовательно. Перемешав указатели в массиве — уже не получится последовательный обход памяти. S>Нам обещали работу с byte[] через misc.Unsafe, чтобы избежать boxing penalty. Я уже запасся попкорном и орешками, т.к. раньше такого не видел.
Не флейма ради, а дополнения для. В C# всё таки у нас есть средства для типизированного доступа к памяти (blittable структуры + указатели). А на фоне align/pack и x86/x64 работать руками с byte* грустно.
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Сложность вставки в середину std::deque — линейная.
Это типа ключ к производительности?
EP>2. Value types они разные бывают, например может быть вот такой: EP>
EP>Опять таки, то что на Java можно написать быстрый код дорогой ценной — я сказал в том же сообщении.
У вас обоих код тормозной и написан за минуту. С тем отличием, у mik1 код без запашка.
EP>Даже с обычными строками/контейнерами переменной длины получается вот какая штука: если в класс Foo добавить под-объект строку, то в случае Java в самом объекте будет хранится указатель на объект в котором хранится указатель на буфер. В C++ же будет указатель на буфер попадёт в сам объект класса Foo — уже на одну индерекцию меньше (не говоря уже об оптимизациях коротких строк в случае которых сам буфер будет внутри объекта класса Foo).
Про строки вообще не по адресу: строки в Java неизменяемые, в отличие от C++, где приходится копировать содержимое, чтобы не иметь race conditions и/или тормозов на синхронизации.
Здравствуйте, Aртём, Вы писали:
EP>>Сложность вставки в середину std::deque — линейная. Aё>Это типа ключ к производительности?
Это такая структура данных. Структуры данных бывают разные, и каждая полезна при каких-то определённых условиях
EP>>2. Value types они разные бывают, например может быть вот такой: EP>>
Изучай
EP>>Опять таки, то что на Java можно написать быстрый код дорогой ценной — я сказал в том же сообщении. Aё>У вас обоих код тормозной и написан за минуту. С тем отличием, у mik1 код без запашка.
Как минимум с тем отличием что у mik1 логическая ошибка, как раз в самом характерном месте. Писал бы он медленный Java-style с объектами Complex — такой ошибки бы не было.
Уже третьи сутки пошли, а корректного кода на Java так и нет.
EP>>Даже с обычными строками/контейнерами переменной длины получается вот какая штука: если в класс Foo добавить под-объект строку, то в случае Java в самом объекте будет хранится указатель на объект в котором хранится указатель на буфер. В C++ же будет указатель на буфер попадёт в сам объект класса Foo — уже на одну индерекцию меньше (не говоря уже об оптимизациях коротких строк в случае которых сам буфер будет внутри объекта класса Foo). Aё>Про строки вообще не по адресу: строки в Java неизменяемые, в отличие от C++, где приходится копировать содержимое, чтобы не иметь race conditions и/или тормозов на синхронизации.
Это вообще ортогонально — в Java можно создать mutable строку, в C++ — immutable
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>>>Сложность вставки в середину std::deque — линейная. Aё>>Это типа ключ к производительности? EP>Это такая структура данных. Структуры данных бывают разные, и каждая полезна при каких-то определённых условиях
Вы сначала привели std::deque как пример производительности, потом в кусты. Нехорошо.
EP>>>2. Value types они разные бывают, например может быть вот такой: EP>>>
Aё>>Поля объекта вектор для Вас это value type?
EP>Изучай
Гуглить я умею. Вы не ответили на мой вопрос- Вы действительно считаете, что поля объекта data типа vector являются типами по значению для типа Foo? Или таки при копировании Foo для data будет вызван копирующий конструктор?
EP>>>Опять таки, то что на Java можно написать быстрый код дорогой ценной — я сказал в том же сообщении. Aё>>У вас обоих код тормозной и написан за минуту. С тем отличием, у mik1 код без запашка.
EP>Как минимум с тем отличием что у mik1 логическая ошибка, как раз в самом характерном месте.
Не вдавался в подробности, что там нарушил mik1 при перемножении- но сомневаюсь, что дело в адресной арифметике. Вообще как-то удивляет, что вроде бы более низкоуровневый программист на C++ боится адресной арифметики в Java и вообще не ожидает такого от Java-иста. К слову, я видел достаточно много тормозного кода на C++, и часто по той же причине что и тормозной Java код- человек не понимает, что он пишет, не понимает сложность алгоритмов, цену синхронизации и т.д.
EP>Уже третьи сутки пошли, а корректного кода на Java так и нет.
Дам Вам вопрос на засыпку- напишете без сторонних библиотек элегантный и быстрый код для reverse matrix со стороной N?
EP>Это вообще ортогонально — в Java можно создать mutable строку, в C++ — immutable
Просто для информации- в Java String immutable из коробки, в C++ std::string mutable из коробки.
Здравствуйте, fddima, Вы писали: F> Не флейма ради, а дополнения для. В C# всё таки у нас есть средства для типизированного доступа к памяти (blittable структуры + указатели). А на фоне align/pack и x86/x64 работать руками с byte* грустно.
Про C#/CLR вопросов нет — там сразу отдавали себе отчёт в том, что сохранить девственность обойтись без структур не выйдет.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.