Пользователь
7,2
рейтинг
4 ноября 2008 в 11:54

Разработка → Разработка на PC и производительность — Memory Latency

Herb Sutter (автор Exceptional C++, бывший глава ISO C++ standards committee, мистер Free Lunch Is Over и прочая, и прочая) работает в Microsoft и иногда по средам читает атомные лекции.

Я наконец-то на одну такую попал, и очень радовался. На умных мужиков всегда радостно поглядеть и послушать.
Для отчета — кроме Херба, видел живого Олександреску и живого Walter Bright (который "D").

Лекция называлась «Machine Architecture: Things Your Programming Language Never Told You» (здесь можно скачать презентацию и видео) и была про конкретную часть abstraction penalty — Memory Latency.

Я попытаюсь коротко рассказать о ключевой мысли лекции. Она простая, очевидная и тысячу раз сказанная. Думаю, еще раз повторить азбуку — никогда не повредит.


Для самых маленьких, о том что такое Latency и Bandwidth


Bandwidth — это ширина канала. Сколько можно прокачать данных за секунду, сколько можно пустить инструкций чтобы полностью загрузить ALU и так далее.
Latency — это длина канала, то есть через какое время к тебе придут данные, которые ты попросил. Через сколько тактов к тебе придет запрошенный бит из памяти, через сколько тактов будет готов результат инструкции, когда команда пройдет до конца пайплайна и так далее.
И они, разумеется, друг на друга влияют. Как только нужен результат, а делать больше нечего — весь bandwidth простаивает из-за latency. Запросили память, которой нет в кеше — сидим, ждем память. Захотели выполнить инструкцию, которой необходим результат предыдущей — ждем ее выполнения. Это создает «пузыри» в канале и соответственно уменьшает загрузку.

Херб в презентации использует пример нефтепровода, он вполне наглядный. Можно прокачивать дикое количество баррелей в минуту, но каждый баррель идет до места назначения несколько дней. В чистом виде bandwidth и latency.

Практически важный момент в том, что bandwidth всегда легко покупать. Поставить два процессора, брать из памяти за раз в два раза больше данных, поставить два компьютера в конце концов. Latency же гораздо дороже — две женщины не родят ребенка за 4.5 месяцев, и продвигается оно только прогрессом — увеличивать частоты, уменьшать размеры элементов, менять технологию и так далее.

И вот последние 20 с лишним лет показывают, что latency растет гораздо медленней. Особенно — latency памяти.


Ща, у Херба там табличко была…

                                 
                    1980 VAX-11/750    Modern Desktop      Improvement since 1980 

Clockspeed (MHz)            6           3000                +500x 

Memory size (RAM, MB)       2           2000                +1000x 

Memory bandwidth (MB/s)     13          7000(read)          +540x 

                                        2000(write)         +150x 

Memory latency (ns)         225         ~70                 +3x 

Memory latency (cycles)     1.4         210                 -150x (!!!!!!)


Из таблички хорошо видно, что процессор хорошо растет, размер памяти хорошо растет, bandwidth памяти опять же зашибато, а вот latency со времен VAX — стало всего в три раза лучше. В расчете на такты (последняя строка) — ухудшилось в 150 раз.
Что означает, что промах кеша стоит на порядки больше даже самых тяжелых инструкций процессора.

В 80-х годах было просто и здорово — стоимость доступа к памяти была вполне сравнима, а то и меньше, вычислительных инструкций (а на floating point так и вообще),
Есть процессор, диск и память, программист ими непосредственно и оперирует. Код выполняется прозрачно и предсказуем до такта.

Сейчас же в железе на самом деле все по-другому. Доступ к памяти — сотни тактов. Да, за раз можно взять целый cache line (32 или 64 байта), но ждать все равно сотни тактов. В миллисекунду, например, получается обратиться в разные места памяти примерно 10000 раз. 100 объектов разных классов, вызов 10 виртуальных функций в каждом — уже 20+% от миллисекунды. В геймдеве — очень реальные цифры. А трафик памяти, вообще говоря, самое важное что у нас есть.

И это все про память. Если полезли к диску — это уже совсем за пределами добра и зла, там latency в десятки миллионов тактов.

Как это лечить — разумеется кешем и иерархией. L1 — 2 такта, L2 — 14 тактов, L3 — lets say about 40. Отдельно для данных, отдельно для инструкций.
Сложная логика кеша, ноу-хау различных производителей процессоров и прочее.
Кроме этого — обязательно out of order, чтобы пытаться выполнять то, что не зависит от ждущих.
Out of order execution, register renaming, обязательно мощный branch prediction, обязательно стартовать доступы и записи в память как можно раньше. Если бранч пойдет не в ту сторону, это сразу рушит out of order и является катастрофой.
Опять же, там внутри длинный конвейер. На P4 был даже патологически длинный — до 25 инструкций за раз и out of order заглядывал вперед на сотню. На последних процессорах конвеер меньше, но все равно непрозрачный.

Саттер пишет, что на Itanium2 кеш занимает 85% площади процессора.
На Core Duo — я не смог нагуглить, думаю примерно также.
Еще 10 с лишним процентов — логика out of order, branch prediction и прочего добра.
Остаются считанные проценты на собственно ALU, которые реально что-то считают.

Современный процессор — это не вычислитель, а гигантский хардверный эмулятор x86-инструкций.
Вся это нужно для того, чтобы спрятать от программиста latency. Чтобы можно было продолжать программировать в 80-х годах — когда есть только процессо и память, причем к памяти доступаться можно сколько угодно недорого. Чтобы продолжать запускать старый код все лучше, чтобы новый можно было писать также.

И все же — мы пытаемся скрыть падение скорости в 150 раз! Незаметно для программиста! Не изменяя его структур данных! Так, чтобы он не заметил изменения порядка выполнения инструкций!

Разумеется, это занятие никогда не будет оптимальным.

Из того что программист в некотором смысле живет в стране эльфов, Саттер делает два практических следствия.

Первое — это влияет на корректность программ


Везде, где делаются предположения о последовательности чтений-записей в память, в любимой Саттером многопоточности.
Если, предполагая, что запись int в память атомарна, начать делать lock free взаимодействие тредов — ушибешься.

Например:

Thread1:
flag1 = 1;
if (flag2 != 0) { …}
// enter critical section

Thread2:
flag2 = 1;
if (flag1 != 0) { …}
// enter critical section



Тред1 сначала выставляет flag1 — флаг того, что он хочет shared resource, и проверяет не занят ли второй ресурс другим тредом. Делается предположение, что flag2 проверится только после установки flag1 (чтобы не войти в critical section если она занята другим тредом).
И будет тотальный превед — memory read на flag1 произойдет очень рано из-за out of order (формально, этот read ни от чего не зависит, поэтому его можно делать рано), и никакой синхронизации не будет.
Поэтому нужно честно локать. Полагаться на память как на что-то, что отражает значения переменных — нельзя.

Второе и самое веселое — конечно, производительность.


Уже давно в основном тормозит память. В основном из-за latency, а не bandwidth. Случайное чтение памяти — много дороже целой тучи вычислений. Locality matters, на всех масштабах.

Кстати, что такое «случайное» в реальной программе страшно размазывается из-за непрозрачной иерархии кешей.
Вроде бы если используется много — то и так будет в кеше. С другой стороны, сколько реальный working set в разные моменты — толком и не прикинуть.
А еще оно на каждом процессоре разное. А еще оно крайне зависит от данных. И самое классное — его еще и хрен померять!
Свел пример к синтетическому — он стал помещаться в кеш. Превед.

К счастью (к сожалению?), цена кеш-мисса столь велика, что серьезные проблемы можно померять и сквозь толстую прослойку.
Скорость random access (меряем latency) против sequential access (меряем bandwith) отличается на порядок. Это разница между std::vector vs std::list.
Хуже, это может быть разница между std::vector<T> vs std::vector<T*> (это, как все знают, и массив объектов в Java или .net ).

В итоге — надо всегда думать о памяти. Как о локальности, так и о затратах.
Мерять, не в память ли уперся. Когда в random access — можно продуктивно думать и решать. И когда в footprint — бывает тоже.

На gamedeff вот тут описывался хороший пример такой борьбы за локальность.

Но точно померять и предсказать все равно не получается. Все очень толсто, нелинейно и непрозрачно. Под тобой работает большая машина с непонятной логикой и, что хуже, непонятной загрузкой. Оживет в бэкграунде сеть и все спутает. Или индексер, упаси господь.

И я не знаю, что с этим делать в PC-мире


Вы уж простите, я из приложений писал только игры и буду рассуждать и сравнивать платформы только на примере любимого геймдева.

С одной стороны, хочется больше контроля. Иметь четкое место в кеше, где я могу иметь гарантированное время доступа. Иметь некие гарантии того, что мне не попортят кеш при первом же context switch.
Вот например, легко рассуждать о том, как хорошо все в консольном мире, где совсем другое железо. SPU, 256 kb полностью управляемой очень быстрой локальной памяти, четкие запросы в основную память широкими (чтобы прятать latency) DMA-пакетами. Или Xbox360, где можно локнуть на время часть кеша, да еще и попросить GPU из него рендерять.
Ни одна из этих моделей не заживет на PC в чистом виде.
На одном процессоре живет множество тредов одновременно, если каждый будет управлять 256 килобайтами памяти, то при context switch ее всю надо выгрузить и загрузить. Будет тяжелый и долгий context switch, а типично в OS ну просто дофига даже полу-активных тредов.
Локать кеш нельзя позволять по тем же причинам — это означает либо буфферить его в память при context switch, либо забирать его навсегда от других приложений. Если забирать будут даже только активные — остальное станет тормозить.

Хуже, основные аппликейшены — без всяких верхних границ. Могут загрузить документ и в 10 килобайт, и в 100 мегабайт. Размер Excel-таблицы может отличаться в тысячи раз, никаких верхних границ по памяти, как на консоли — не поставишь.

Причем и набор железа, и количество памяти всегда разное, таргет вязкий — «кушать памяти поменьше и работать побыстрее». И железо больше эмулирует, чем работает.

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

И это малая часть проблем. Я бы сказал, фундаментальные — backward compatibility и совсем другой чем на консолях баланс «performance против стоимости разработки». Но об этом можно как-нибудь потом писать бесконечно много.

Напоследок, краткие медитативные цифирки (я брал у себя на домашней машине):

floating point mul: 0.5-4 cycles (на одном ядре)
L1 access (~16-32 kb): ~2-3 cycles
L2 access (~2-4 mb): ~15 cycles
Random Memory Access: ~200 cycles
Sequential Access with Prefetch: ~2 bytes/cycle

Остается бороться, мужики. Понимать цену абстракции и на этом уровне, не давать мозгам расслабляться и жить в восьмидесятых годах.
Семен Козлов @sim0nsays
карма
164,7
рейтинг 7,2
Пользователь
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

Комментарии (70)

  • 0
    Огромное спасибо за интересную статью!
    Для меня сейчас, вы — самый интересный автор на хабре )
  • +7
  • 0
    а где бы про это можно подробней почитать??
    желательно с простыми примерами и с самого начала…

    пишу ресурсоемкие приложения на c++ (имидж процессинг), знаю что можно ускорить, но не знаю как ö(
    • +1
      Линк из предыдущего коммента очень хороший, начинать читать надо там ( lwn.net/Articles/250967/ )

      Если Image Processing — еще обязательно мануалы по SSE.
      Классические от Интела (http://www.intel.com/products/processor/manuals/), документацию из MSDN, и пару любых туториалов из гугла.
      Ну там, вот
      • 0
        спасибо за SSE, буду изучать.
        А есть ли здесь знатоки/любители CUDA ??
        • 0
          Ну, я знаю что-то о CUDA, мне по должности положено. На простые вопросы отвечу, за сложными лучше идти на специализированные форумы.
    • 0
      Использовать IPP, там уже все ускорено за вас.
      • 0
        К сожалению, в случаях хоть чуть отличающихся от мейнстрима, IPP может стать использовать тяжело.
        Но когда можно использовать — конечно нужно.

        Еще IPP хорошая проверка, насколько ты хорошо или плохо пишешь такие функции :)
        Можно проигрывать проценты, но не разы.
  • –4
    Очень познавательно. Я еще в университете забросил C++ из-за постоянной борьбы с компиляторами и проблемами выполнения кода на разных компьютерах. Ваша статья, отчасти, помогла понять чать проблем и то, почему многие программисты ругают современный подход Intel к проектированию процессоров.
    • +2
      Какой такой подход? x86 в отличие от любых других современных процессоров может выполнять неоптимизированное мясо, коим являются 90% программ, с хорошей скоростью.
      • +1
        Процессор, ориентированный на мясо… (надо будет запомнить...) — как все универсальное: все делает, но хуже, чем узко-специализированные решения.
  • +14
    Впечатлило. Так вот оказывается почему консоли могут выдавать прекрасную графику на сравнительно средней аппаратной начинке.
  • 0
    А вот вопрос к специалисту — а как с этим обстоят дела на больших компьютерах? Ну всяких спарках сановских, креях и прочих мегадолларовых устройствах?
    • 0
      А я не специалист ни разу по серверному железу. В Спарках вроде бы тот же DDR, так что проблемы все на месте. На сервере попроще, реалтайм-перформанс не так критичен.
      За Креи совсем не знаю.
      • 0
        реалтайм-перфомансе важен в oltp, так-что там все тоже самое, только помноженное на промышленную эксплуатацию. :(
        • 0
          Я скорее в том смысле, что мне казалось, там важен bandwidth — сколько удается обработать запросов в секунду, а не latency — сколько занимает один запрос. В таком случае, проблемы в крайнем случае можно решать деньгами — увеличивать количество серверов и т.д., временем программиста, соответственно, только если оно оказывается дешевле серверов. Чем дальше ужимаешь — тем больше нужно усилий, в пределе — design for performance, войны за такты и прочее.
          В реалтайме же такого размена вообще нет — критично время работы одной задачи на одной машине прямо здесь и сейчас. Становится веселее.
          Впрочем, это я патриот низкоуровнего перформанса.

          Оффтоп: интересно, как бы железную загрузку процессора показательно померять, чтобы сравнить…
          • 0
            В программе top в линухе есть такое поле — wa. Оно вроде как означает «waiting for IO» — процент времени, который проц проводит в ожидании ответа, не выполняя полезной работы. Ощутимо подскакивает во время плотного взаимодействия с диском — своппинг, например…

            Ваш оффтоп — не из этой серии?
            • 0
              Мне скорее хочется процент утилизации железа. Насколько нагружены ALU, например.
              • 0
                В спарке есть счетчики циклов на каждом блоке, так что можно померить как кого грузили.
  • +8
    Чуствую себя лохом :(
    Засиделся в пхп, пожалуй надо опуститься на low-level, хотя бы ненадолго.
    • НЛО прилетело и опубликовало эту надпись здесь
  • –2
    Random Memory Access: ~200 cycles — это хорошо или плохо? А сколько у вас цикл? Чтобы не было таких глупых вопросов Latency измеряется не в циклах чего-то там, а в секундах — наносекундах. Поэтому у автора и такие бредовые результаты с ухудшением латентности в 150 раз по сравнению с 1980.
    • +3
      Только всё равно процессор простаивает 200 циклов, а мог бы делать полезную работу. Конечно, иногда out of order исполнение спасает, но не так часто, как хотелось бы.
      • 0
        Кто вам сказал что он простаивает эти 200 тактов? 200 таковый LLC miss+DTLB miss — это надо постараться так писать программы, чтобы у вас при каждом обращении в память такие простои были. А если промах один-два, то эти промахи скрадываются Out-Of-Order выполнением других инструкций.
        • +1
          С трудом себе представляю внеочередное выполнение сотни независимых, например, двухтактовых комманд. Если повезёт, выполнится две-три командны, остальные 190 тактов процессор будет крутится вхолостую.

          Что же до промахов, любой список указателей на данные в куче потенциальный источник таких катаклизмов с высокой вероятностью.
        • 0
          точнее говоря, тут не только в программе дело

          компилятор (статический оптимизатор) + железо (динамический out-of-order) делают свои дела. Причем на ILP (instruction level parallelism), то бишь железо, приходится основная доля распараллеливания в самом (самих) пайплаине (пайплаинах).

          Кроме того не стоит забывать о MOB, L2 и victim cache.
        • НЛО прилетело и опубликовало эту надпись здесь
          • 0
            FFT кстати отлично переписывается на регулярные доступы. Матричное умножение отдельными локальными блоками порядка размера кеша.
            Вот тут показательный пример — lwn.net/Articles/255364/
            • НЛО прилетело и опубликовало эту надпись здесь
        • 0
          Два кеш-мисса — это значит out of order должен предоставить инструкций на 400 тактов, то есть сотни. Это очень немало, их вполне может не найтись.
          На самом деле, Hyper-Threading не в последнюю очередь был придуман затем, чтобы сглаживать такие простои. Пока один тред ждет на доступе к памяти, другой может выполняться. Но даже двух тредов мало, когда оба начинают генерировать стабильные кеш-миссы.
    • +2
      Вычислительная операция как была такт, так и осталась тактом (с учетом SIMD-операций и multicore, еще меньше). В 150 раз ухудшилось соотношение скорости памяти к скорости процессора. Это принципиально меняет факторы, влияющие на производительность приложения.
      • 0
        Вычислительная операция — это абстрактное понятие. SSE делает 2 дабловых умножения за такт. 1 дабловое умножение при этом занимает 0.5 такта. Сингловое умножение, соответственно 0.25 тактов. А сейчас в Блумфилдах будет плавающий множитель и режим турбо, и такт у вас будет такой, чтобы влезать в TDP.
        >>В 150 раз ухудшилось соотношение скорости памяти к скорости процессора. Это принципиально меняет факторы, влияющие на производительность приложения.
        Это как раз не меняет. Как раньше хреново было, так и сейчас. Ничего нового. А вот ООО, кэш, префетч, предсказание переходов — это да, это — меняет.
        • 0
          Дык нет же. Раньше было совсем не так, вычисления были сравнимы с доступом в память. Ну комон, если раньше люди для того чтобы программа работала быстрее чаще пытались делать на сложение меньше, то теперь надо смотреть и думать о локальности памяти. Когда скорость доступа к памяти сравнима с обычной инструкций — вообще проблемы локальности не стоит.

          А вот когда она есть — тогда надо делать и out of order, и кешировать, и префетчить, и выбирать структуры данных.

          Мне кажется, если честно, у нас какое-то номиналистическое непонимание. Вы утверждаете «скорость доступа к памяти не увеличилась, ничего не поменялось». Я утверждаю «но на все остальное действовал закон Мура, и поэтому вес этого фактора принципиально возрос».
  • 0
    «Поставить поставить два процессора» — исправьте пожалуйста.
    • +1
      Поправил, спасибо.
  • +7
    Отличная статья.

    По поводу latency vs bandwidth говорят: «Bandwidth problems can be cured with money. Latency problems are harder because the speed of light is fixed – you can’t bribe God.»
  • 0
    Практический вопрос: для скриптовых языков типа php или perl, c огромным расходом памяти, лучше использовать два медленных процессора вместо одного быстрого, получается? Есть ли конкретные рекомендации на эту тему — например, несколько бакэндов + фронтэнд vs один бакэнд+фронтэнд? И какое влияние многоядерности на доступ к памяти — будут ли двухядерные процессоры в сумме иметь меньшие потери производительности из-за латентности, чем одноядерный большей частоты в два раза?
  • +1
    Многоядерность она разная бывает. В исполнении с общей FSB многоядерность ухудшает доступ к памяти, поскольку вводятся дополнительные затраты на синхронизацию кэшей (снупинг). В исполнении NUMA все хорошо, когда каждое ядро вделяет память симметрично. Но как только одно ядро залезло в память другого — все, опять тормозим.
    Я честно скажу — не занимался профилированием скриптов, но на первый взгляд — высокая частота+оч большой кэш — вот что для них нужно. А какие-то вычислительные задачи лучше писать на С-подобных языках с жесткой оптимизацией под платформу — компилятором и/или руками.
    • 0
      Очень большой кеш — прямое следствие latency памяти. Уверенно пребывать в иллюзии быстрого доступа к памяти можно только если есть уверенность, что твой working set полностью в кеш влезает. Это вряд ли. Но большой кеш сглаживает степень падения, конечно :)
  • +2
    Извините, но Александреску… Как-то странно видеть написание его фамилии через «О».
    А статья правда интересная! Спасибо!
    • +1
      Дык эта, падонак-стайл. Я еще Оволон пишу, вместо WPF.
  • 0
    Можно ли считать процессоры без MMU/TLB более простыми, но и прогрессивными в архитектурном плане? (типа ARM'ов, как в сотовых телефонах и микроконтроллёрах)
    Будущее за простотой! Долой многоуровневую эмуляцию?
    • 0
      с 64-битовой адресацией без MMU можно без проблем жить, наверное. Но ведь виртуальная память — это не только эмуляция, но и изоляция.
      Хотя было бы здорово иметь одну абстракцию на дисковую память и физическую :) Соответственно, и механизмы защиты позаимствовать.
    • 0
      Все, как всегда, сложно. Процессорам на открытах платформах с обратной совместимостью — боюсь, придется играть в эти игры. Потому что а) людям не хочется шибко много думать, когда они пишут код и б) есть очень много уже написанного кода, который хочется запускать быстрее.
      Действительно «прогрессивные» в этом плане скорее Cell и Larrabee.
  • –2
    Вот, наконец-то поднимают эту тему! Сегодня проблемой десктопных приложений еще и становится то, что лентяи-программисты используют либо языки вроде явы/дотнета, либо библиотеки вроде Qt, которые, кроме всего прочего, отличаются непомерным большим потреблением памяти, в результате чего (я подозреваю) происходит намоного больше обращений к RAM так как эти монстры просто физически не могут поместиться в кеш.

    Кроме, того в ООП-библиотеках использутся многократное наследование, на каждом этапе в класс добавляются новые поля, в результате чего экземпляр класса занимает достаточно много места в памяти, и если многие поля не используются, то они все равно вытягиваются в кеш и отнимают там местло, так как все хранятся рядом.
    • НЛО прилетело и опубликовало эту надпись здесь
      • –2
        Java и NET (пока что) место на сервере, а не на десктопе.

        Множество программ, начаная с классических winRAR/winAMP/foobar2000 и так далее написаны без всего этого и замечательно работали/работают.

        А тенденция использовать упомянутые технологии меня, как пользователя, не радует (а линусоидам еще хуже, там вообще пытаются к скриптовым языкам прикручивать Gtk, надеюсь вы и сами понимаете, какой ужас в результате полуается).
        • 0
          А представьте как быстро .NET идет на КПК…
        • НЛО прилетело и опубликовало эту надпись здесь
    • –1
      Лентяи говоришь?
      А головой подумать?
      Вы же, наверное, не лентяйничаете и не ездите в транспорте, а идёте пешком?
      Всегда есть 2 стороны медали.
      Скорость и минимальность нужна не везде и не всегда. Да, к тому же, за неё приходится платить.
      • –2
        Ну хорошо, лентяи, я немного перегнул, тут скорее рыночные обстоятельства, то есть разработчику/программистам нужно реализовать выполнение программой каких-то задач к какому-то сроку, а уж насколько качественно это будет сделано — дело десятое, наверно писать исключительно хорошие программы невыгодно, где-то я читал… не помню, может у Споэльски.
        • НЛО прилетело и опубликовало эту надпись здесь
          • 0
            Боюсь, вы неправильно меня поняли. Я говорю о производительности языков для десктопных приложений, а не серверных. Согласен, на сервере можно хоть на Руби писать, так как всегда можно обеспечить нужную производительность покупкой хорошего железа, настройкой ОС, кешированием, масштабированием и прочим.

            Пользователю важно, чтобы у него все работало быстро, и никто не будет против, если вы напишете скрипт, делающий хоть 1000 запросов к бд, если сможете обеспечить производительность.

            Но десктопные приложения — другая область, здесь перед разработчиком другой уровень требований, и писать надо программы, эффективно использующие ресурсы компьютера (а не вести себя так, как будто пользователь будет запускать только вашу программу и больше ничего параллельно). Перечисленные мной технологии этим требованиям отвечают плохо.

            Другой вопрос, что с экономической точки зрения это не очень выгодно, выгоднее делать как придется. Но это извечный вопрос — сделать кое-как или качественно.

            А в веб-технологии соотверственно внимание стоит уделять производительности client-side технологий, например js (многие приложения Гугла, например, на мой взгляд в этом плане сделаны так себе, авторы увлеклись созданием сложных интерфейсов на языке, который для этого не очень подходит).

            Что касается вопроса про язык для десктопа — очевидно, нужно что-то вроде С++, только было бы замечательно, если б его кто-то подпилил, решив проблемы, начиная с классической проблемы исключений в конструкторе, и придумав нативные и производительные масивы и строки. Ну и мне. как человеку ленивому хотелось бы писать поменьше, то есть сделать автогенерацию заголовочных файлов, убрать необходимость описывать всякие структуры (автогенерация описания структуры, почему бы нет) и типы данных там, где они очевидны. ах, да, и include_once сделайте пожалуйста (или вообще уберите нафик заголовочные файлы) (не понимаю. почему никто до этого не додумался).

            Ну и касательно библиотек (Gtk, Qt), они действительно неэффективны, соравните производительность наитивных Win приложений вроде notepad с такими же, написанными на этих библиотеках. Как говорится, разница видна невооруженным глазом. Ну и то, что имитировать ООП на Си — явное извращение, не стоит забывать (я читал про причины, побудившие это сделать, тем не менее это слабое и неэффективное решение).
            • 0
              Качество тут не при чём. Хотя что именно Вы имеете в виду говоря «качество»?
              Для меня качество — это точность в решении поставленной задачи. Насколько хорошо решена задача? Вот что главное.
              На шарпе пишут и хорошие, качественные программы, хотя жуют они больше чем жевал бы аналог но на С/С++
              А ведь часто скорость в решении — не главное. Программа не обязательно должна быть «ультра» быстрой она должна быть достаточно быстрой для своей задачи. Тут важно соблюдать баланс. Разработчики часто перестают проверять perfomence вообще, а вот это уже плохо. Хотя крайности — обычно всегда плохо…
              • 0
                Если кратко: компьютер не должен реагировать медленнее мысли, человеческого мозга. Иначе пользователю приходится ждать, а это некомфортно.

                > Для меня качество — это точность в решении
                > поставленной задачи. Насколько хорошо
                > решена задача? Вот что главное.

                Не путайте, повторю еще раз, десктопные приложения и серверные или командно-строчные скрипты. Одно дело — скрипт, который гудит где-то в недрах сервера, часами обрбатывая большой объем данных, железке пофиг, другое дело, то, что у меня, живого человека)) на экране.

                Десктопное приложение (которым пользуются повседневно, а не 1 раз, посмотрел — снес) не должно потреблять неадекватное количество памяти, не должно медленно запускаться (сплеш-заставка — это анахронизм 95 годов), интерфейс не должен вызывать заметных глазу задержек, и тем более, «замерзать».

                Когда чувствуешь при каждом клике, как событие медленно проваливается сквозь толщу компонентов и обработчиков, или когда на глазах прорисовываются элементы интерфейса, это подрывает весь user-experience.

                Сравните для примера Chrome и Firefox. Первый ест больше памяти (издержки технологии, надеюсь исправят), но запускается почти мгновенно. Что хорошего в браузере, который запускается с такой же скоростью, как последний 3Д Макс?(да и работает не быстрее). Ну и естественно, идею реализациии интерфейса на XUL/JS нельзя назвать грамотной, как и идею выполнять обработку событий интерфейса и JS-скрипты в одном потоке, тут просто сказать нечего. Хотя это и можно объяснить ограниченностью ресурсов у разработчиков (не так богаты, как Гугл все же) и «больной» историей (большое число команд учавствовало в разработке, в таких случаях архитектура страдает).

                Какой смысл тогда подключаться к многомегабитному интернету, если страницы прорисовываются дольше, чем приходит очередная порция данных из сети?
                • –1
                  >компьютер не должен реагировать медленнее мысли
                  Это в идеале. А в жизни всё сложнее.
                  >Не путайте, повторю еще раз, десктопные приложения и серверные или командно-строчные скрипты
                  Я не путаю. Когда я говорил про достаточную скорость я имел в виду все программы, вне зависимости от применения.
                  >но запускается почти мгновенно
                  Вот когда к нему прикрутят весь тот плагинный функционал что есть у фф тогда и будем сравнивать.

                  Вы приписываете мне свои мысли.
                  Скорость должна быть достаточной. Для любой программы.
                  • 0
                    > Вот когда к нему прикрутят весь тот
                    > плагинный функционал что есть у фф
                    > тогда и будем сравнивать.

                    Тормознутость браузера перечеркивает все преимущества плагинов. И эту тормознутость ничем не исправить, надо только подождать пару лет, когда железо станет помощнее. Если конечно программеры FireFox не придумают еще какуб-нибудь ресурсоемкую хрень.

                    Что касается скорости работы программ — это непосредственно связано с юзабилити, удобством использования. Хотя возможно, улучшение юзабилити не является для кого-то приоритетом.

                    >компьютер не должен реагировать медленнее мысли
                    > Это в идеале. А в жизни всё сложнее.
                    Не вижу ни одной убедительной причины, по которой программа может притормаживать на процессоре, выполняющем больше миллиарда (!) операций в секунду. Если программа делает что-то мега слодное — выведите градусник, но томрозов тем не менее быть не должно. Пользователь мог бы ввести поисковый запрос и сидеть смотреть результаты, делать выводы, а вместо этого он должен ждать пока загрузится браузер, тратя свое время. Какой смысл в быстром интернете с медленным браузером, объясните?
                    • –1
                      >Какой смысл в быстром интернете с медленным браузером, объясните?
                      Видео смотреть удобнее.
                      >Не вижу ни одной убедительной причины, по которой программа может притормаживать на процессоре, выполняющем больше миллиарда (!) операций в секунду.
                      Вы никогда не задумывались почему производители браузеров — огромные компании с миллионными оборотами? С большим штатом программистов? Даже целые войны были.
                      Неужели Вы действительно умаете что всё так просто?
            • НЛО прилетело и опубликовало эту надпись здесь
              • 0
                Если кратко — в общем, вы правы. Я абсолютно не против использования библиотек, конечно, не писать же свою функцию printf() ))) Более того, нет наверно никакого смысла писать все самому, то, что уже написано и отлажено до тебя тысячей человек. Но почему люди просто тупо статически линкуют библиотеку целиком, даже если используют меньшую часть функций? (подозреваю, в опенсорсе это связано с тем, что gcc не умеет function-level linking)

                Другой вопрос, что библиотеки бывают разные. Упомянутые мной Gtk и Qt (мое имхо) потебляют неадекватное количество ресурсов, посмотрите, сколько времени будет выполняться HelloWorld. Другой вопрос, что они дают чот-то вроде кроссплатформенности, но не дорогая ли выходит плата за кроссплатформенность? Особенно учитывая крошечный процент пользователей не-Win систем. Получается, что 97% человек платят за то, чтобы у оставшихся 3% эта программа тоже работала.

                Другой пример. Есть такая замечательная программа DropBox. У нее очень классная задумка, а вот реализация — подкачала (именно десктопного клиента, к веб-инетрфейсу претензий нет). Эта программа, даже ничего не делая, сидя в трее потребляет под 50Мб памяти, как вы думаете, почему? А загляните-ка в папку программы и увидите там во-первых, Python25.dll, значит минимум часть программы написана на питоне, уже понятно, куда девается память и возможно скорость работы. Теперь заглянем в 24 мегабайтный екзешник, который представляет собой мало того, что debug-версию (руки бы поотрывать), так еще и является архивом. да-да, не ослышались, это архив, видимо во время запуска он куда-то распаковывается, на диск или в память. В архиве — тонна файлов и папок, ощущение, что это пакет с исходниками ядра Линукса)) Но нет, там куча (слава богу, откомпилированных) Питоновских файлов и библиотек. Ах да, еще несколько внушительного размера библиотек вроде wxmsw28uh_core_vc.dll (3 мб, нехилый размер для core). Вот и обяъяснение памятежоркости — Питон + WxWidgets. Нафига им сдался питон и WxWidgets — не пойму. неужели нет на С++ хороших библиотек. что творится-то? Или они денег все стоят? И почему, блин, Питон, если уж его использовать, не компилируется в машинный код.а превращается в какую-то хрень, помесь архива и exe-файла? По моему, так просто Питон под windows никому особо не нужен, вот все на его оптимизацию и забивают.

                Вот такие вот печальные дела(
                • –1
                  >Особенно учитывая крошечный процент пользователей не-Win систем. Получается, что 97% человек платят за то, чтобы у оставшихся 3% эта программа тоже работала.
                  Ага.
                  >debug-версию
                  А как Вы это узнали, если это архив?
                  >на С++ хороших библиотек. что творится-то?
                  Это называется прогресс. Кроме С++ в мире есть ещё много хороших языков программирования.
                  >И почему, блин, Питон, если уж его использовать, не компилируется в машинный код
                  >По моему, так просто Питон под windows никому особо не нужен, вот все на его оптимизацию и забивают.
                  Потому что он — интерпретатор. Вы бы для начала почитали что это такое, а потом уже критиковали.
                  Если он вам не нужен — это ещё не значит что не нужен никому.
                  Я уже не говорю о том что без этих «медленных и не нужных» (Python, C#, Java, Tcl ...) языков не появилось бы куча программ. Просто потому что их сложнее было бы делать.
                  • 0
                    > А как Вы это узнали, если это архив?

                    PEiD пишет MS VC 7.0 [ZIP SFX][Debug], а Тотал коммандер открывает содержимое (да-да, он и такое умеет)).

                    > Потому что он — интерпретатор. Вы бы
                    > для начала почитали что это такое, а
                    > потом уже критиковали.

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

                    > Я уже не говорю о том что без этих
                    > «медленных и не нужных» (Python, C#,
                    > Java, Tcl ...) языков не появилось бы куча
                    > программ. Просто потому что их сложнее > было бы делать.

                    На сервере — пожалуйста. Там за железо платит разработчик, а не пользователь)
                    • –1
                      >путь наименьшего сопротивления
                      ну я понимаю, нужно всегда использовать трудный путь.
  • –1
    Разве не об этом Кнут не так давно говорил?
  • 0
    PC, конечно, изрядно нагружен обратной совместимостью, его тормозит эта самая latency, но процесс геймдева на консолях тормозят гораздо больше высокоуровневых вещей: закрытость и коммерческий характер платформы, отсутствие «любительского» движения разработчиков (моддеров и т. п.), не успевающие за законом Мура маркетинговые циклы… поэтому я спокоен за ПК и даже не собираюсь покупать какую-либо консоль. (Давно что-то у нас не было холиваров на эту тему...:))
    • +1
      Я готов и всегда рад разговаривать о вкусе устриц с кем-то, кто их давно и долго кушает. Где-то высказывались мнения людьми, лет 5 разрабатывающими под консоли?..
  • –1
    Вводная статья (обзорная) в архитектуру железок и проблему производительности приложений. Если автор хотел раскрыть тему производительности, то, думаю, этого не получилось. Только масса вопросов и домыслов родилась у всех… надо либо раскрыть до конца, либо не соваться в эту тему.

    Статья породила в комментариях (мне кажется) холи вар среди сторонников managed и unmanaged языков программирования. Одни ругают их за «обжорство» и говорят «ай да низкоуровневое программирование», другие — отстаивают, хвалят их за скорость разработки приложений. По мне так надо всегда выбирать между оптимизированным, вылизанным, быстрым приложением и скоростью его разработки. В первую очередь заказчику (в конечном счёте мы все пишем для какого-то заказчика) надо работающее (корректно, без багов) приложение и в срок. А уж во вторую очередь приложение оптимизированное. Сразу поймать двух зайцев не удастся, уж поверьте. И лучше получит сначала первое, потом второе.

    Кому действительно интересна тема низкоуровневой оптимизации тем рекомендую почитать вот эти вещи:
    The Software Optimization Cookbook
    The Software Optimization Cookbook, Second Edition
    The Software Vectorization Handbook

    Для оптимизации на многоядерных железках:
    Multi-Core Programming
    Optimizing Applications for Multi-Core Processors

    Это, так сказать, отправная точка для тех, кому интересно. А вот «клубничка» — Code Optimization: Effective Memory Usage от Криса Касперского.
    • 0
      Холивора не видел. Что все зависит от требований и не всегда производительность приоритет — ну, в десятитысячный повторять не хочется, понимание читателя подразумевается.

      Тема низкоуровневой оптимизации как таковой — слишком широка, чтобы ее объять одним постом. Или даже книгой, или даже жизнью одного человека. Саттер вот про Memory Latency выступил, Ульрих написал монументальный труд про память как таковую.

      Поэтому я не очень понимаю, как можно целиком тему производительности раскрыть.
  • 0
    Очень интересная статья, с другой стороны жить как-то расхотелось сразу )
  • 0
    На самом деле out-of-order весьма фигово борется с memory wall, особенно в многозадачных и многопроцессорных системах. Предсказатели ветвлений не идеальны, если код не тупо потоковый (считаем сумму элементов массива), а логический (типа анализа того, куда юнит наступил), то они ошибаются очень часто, генерируют ложные обращения к памяти, к TLB, синхронизация кэшей. И вообще прочий ужас.

    Кроме того, никуда нам не уйти от зависимостей. Код, в котором нет зависимостей — это тривиальные примеры, в чём-то более или менее сложных не бывает цепочек независимого кода длиной больше 100 инструкций. И P4 оказался провалом именно поэтому, потому что нет такого когда, который хорошо бы ложился на эти длинные конвейеры… Ну… Или этот код просто бы моделировал сферического коня в вакууме. В реальных программах не так уж и много микропараллелизма (независимостей, скажем, в анализе поведения персонажа в игрушке), зато много параллелизма уровня среднего (несколько моделей можно обсчитывать независимости), который out-of-order cpu просто не видит.

    Поэтому, гораздо более мощное средство борьбы за сокрытие задержек — это SMT. Собственно, отчасти именно поэтому GPU такую звериную пиковую производительность имеют.

    Ну. А борьба за локальность, конечно, актуальна при любой архитектуре.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.