• ReactOS стал самодостаточным в год своего 21-летия
    0

    А вот вопрос: оно у вас всё-еще древним mingw (с msys) собирается? Я собственно не про сам msys/mingw а про build-tools в нём и gcc в частности… Т.е. вот этим вот?


    $ gcc --version
    gcc (GCC) 3.4.4 (msys special)

    А то оно же и правда старое, и медлючее...


    Собирать с новыми build-tools не пробовали? Например:


    $ export PATH=/c/mingw-w64-32/bin:$PATH
    $ gcc --version
    gcc.exe (i686-win32-dwarf-rev0, Built by MinGW-W64 project) 7.3.0

    Да 7.x чуть капризнее (можно запросто UB словить где раньше не было), но зато рвёт все остальные компиляторы как тот Тузик ту грелку, особливо если O3, march=native и т.д…
    У меня в некоторых довольно больших проектах после перехода (и вычистки всех UB;) прирост скорости был 15%-30% (а местами до 50%) по performance-тестам.

  • Боевой космический лазер «Скиф»
    0
    Т.е. c нагревом Солнцем (поверхностей обращенных к нему, от 4K до 470K) справляются, а отвести «такую мощность уже проблематичнее»? Вы не забыли что это импульсная мощность (т.е. не сравниваем с постоянно работающим ядерным реактором с огромными радиаторами, хотя даже для них проекты имеются)?
    Проблемы конечно есть, например как не заморозить хладагент в отводнике от радиаторов, пока лазер не работает (т.е. «створ-шубу» и СОТР какой-никакой ставить придётся) и т.д. и т.п., но они решаемые и ничего сверхсовершенного тут не нужно (даже с технологиями из 90-х)…

    Кстати тут вот неплохая статья от ув. Zelenyikot про теплообмен в космосе…
  • Боевой космический лазер «Скиф»
    0
    Так конвективные чиллеры для мощных лазеров уже в лохматые 90-е прекрасно делали…
    Даже например жидкостные. Грубо говоря, чем более мощный лазер, тем больше объем жидкости (теплоносителя) требуется.
    Т.е. просто таскать с собой бак на 1K литров, для самолёта не самая большая проблема.
    Можете например почитать на досуге.
  • Заблокировать весь интернет, или обезьяна с гранатой
    0
    Это же интернет, а не телевидение. Для него надо двустороннюю связь.

    Правда что ли?...
    В самом худшем случае просто upstream бывает чуть ниже, чем мог бы быть (например даже 2W-sender отдаёт туда 6Mb на раз-два)...

  • Как испортить безопасность паролей, следуя советам с Хабра
    0

    нет, имелось ввиду совершенно другое (см ниже)

  • Как испортить безопасность паролей, следуя советам с Хабра
    0

    Боюсь с вашим дано-найти то не очень работает (если "перец" не есть ключ симметричного шифрования).


    Выше я имел ввиду что посоленные пароли (хеши) перед записью в базу шифруются симметричным алгоритмом (например AES) единственным секретным ключом (aka "k1"), не хранящимся в базе.
    Тогда процедура перешифрования на k2 при возможной компрометации k1 выглядит след. образом:


    for usrid, pwdhash in get_all_usr_pwd():
      pwdhash = AES.decrypt(pwdhash, k1);
      pwdhash = AES.encrypt(pwdhash, k2)
      write_usr_pwd(usrid, pwdhash)

    Если вы подмешали ваш "перец" в процесс генерации хеша (и этот процесс не симметричный), то тогда перешифрование возможно только в процессе авторизации для каждого пользования отдельно.

  • Почему "=" означает присваивание?
    +2

    Проблема есть на самом деле...


    Я вот как-то поправил одну ошибку в коде калибрования некоторого устройства, измеряющего радиационный фон:


    - if ((R = NominalR) || (Rq <= EstimatedMinEnvR)) {
    + if ((R == NominalR) || (Rq <= EstimatedMinEnvR)) {
        R = (R + Rq)/2;
        return;
      }

    Лишнее наверно говорить, что в той версии калибровка естественно не работала, от слова вовсе…
    И это к сожалению не единственный случай на моей памяти.

  • Почему "=" означает присваивание?
    0
    … но долгий опыт показал мне что я — скорее исключение, чем правило…

    Аналогично,… однако мне мой долгий опыт ещё подсказывает, что я видимо не в состоянии привить кому-либо что-нибудь функциональное (я тут не про азы).
    Однако самостоятельно те же люди много позже смогли осилить ну например тот же haskell.
    При том, что с императивными языками любой группы (включая скриптовые, типа питон) никогда особых проблем не наблюдалось (ну если человек в принципе обучаем программированию).

  • Почему "=" означает присваивание?
    0
    Интересно — почему так…

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


    Ну вот простейший пример на haskell:


    -- Example ha.1:
    primes = map head $ iterate (\(x:xs) -> [y | y<-xs, y `mod` x /= 0 ]) [2..]

    Или такой:


    -- Example ha.2:
    primes = 2 : [x | x <- [3, 5..], 
      (
        [
          y | y <- [2..(div x 2)],
          mod x y == 0
        ] == []
      )
    ]

    И сравните это по читабельности ну например с python:


    # Example py.1:
    (x for x in range(2,n) if x == 2 or (x & 1 and not any(y for y in range(2,x) if not x%y)))

    Я не про эффективность тут, а про читабельность, но…
    даже если что-то на сите ...


    # Example py.2:
    def primes():
      '''Generator for primes via the sieve of eratosthenes'''
      mSE = {}
      x = 2
      while 1:
        if x not in mSE:
          yield x
          mSE[x*x] = [x]
        else:
          for y in mSE[x]:
            mSE.setdefault(y+x, []).append(y)
          del mSE[x]
        x += 1

    Вторая причина: не все языки, на которых легко писать код, легко затем и читать.


    Но зато "функциональщина" позволяет перекладывать многия математические формулы практически один в один, см. Функциональное программирование на языке Haskell, стр 109.


    Ну и тут нас догоняет третья причина: как раз про эффективность — не многие представляют себе во что весь этот "сахар" и "соль" в результате развернутся, а хочется же понимать это сразу без утомительного переделывания/оптимизации потом (а мы помним иногда код плохо читается ;).


    У традиционных императивных языков это, как правило, не так, ну или как минимум много очевиднее (и даже при наличии некоторой "магии").
    Т.е. в примере py.1 выше сразу очевидно что критерий not any(y for y in range(2,x) if not x%y) абсолютно не эффективен (уже на относительно небольших числах).
    По крайней мере пока python не научится оптимизировать суб-генераторы.

  • Применение сверточных нейронных сетей для задач NLP
    +7

    Вы серьёзно?.. Ну-ну.


    When we hear about Convolutional Neural Network (CNNs), we typically think of Computer Vision. CNNs were responsible for major breakthroughs in Image Classification and are the core of most Computer Vision systems today…

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

    И т.д. и т.п.
    Вы правда думаете, что изменением пары фраз и заместив 20-30% можно "обмануть" человека бегло читающего по английски?


    Молодой человек, это называется — плагиат.
    Но хоть мораль — дело общественное, совесть всё таки — дело каждого.
    Так что я вам ничего доказывать не собираюсь, оставайтесь при своем мнении.

  • Применение сверточных нейронных сетей для задач NLP
    +1

    Ну это как раз малая часть (и Denny Britz на её первоначальный вариант от 2014 года ссылается)…
    Из статьи же Брица, той что на WildML за 2015 год, практически 70-80% (если не больше).


    предыдущая мне недоступна

    А WildML нынче в реестре? Поискал в блэклисте — говорит вроде нет… Если все же — сочувствую...

  • Что нового в PostgreSQL 11: INCLUDE-индексы
    0

    Потому что только ключ (или ключи) включаются в индекс напрямую, а покрытие (nokeys) соответственно в INCLUDE.
    Грубо причина описана выше.

  • Применение сверточных нейронных сетей для задач NLP
    0
    Статья замечательная, чего мне не хватило, это собственно…
    ссылки на оригинал.
    Укажите пожалуйста, что это, хоть и обрезаный (с отступлениями, вытяжками со стороны и т.д.), но всё же перевод… А то не красиво как-то выходит.
  • Конференция DEFCON 23. «Как я сбивал назойливый дрон соседского ребёнка». Майкл Робинсон
    0
    То понятно конечно, однако мост не мост, но…

    Я не хотел бы быть в самолёте, которому в воздухозаборник движка прилетит какой-нибудь 20-ти килограммовый дрон, тем более в режиме взлёт/посадка (те же 3/8, когда реакция пилота должна быть мгновенной и т.д.).

    Как-то, в бытность свою инженером завода ГА, довелось наблюдать турбину, пропустившую через себя кусочек стайки дроздов (их перемололо конечно… но не без последствий для турбины) — зрелище то еще, доложу я вам.
  • Что нового в PostgreSQL 11: INCLUDE-индексы
    0

    Иии… что там должно чем отличатся?
    Вы правда про запрос по одной row спрашиваете (я напомню кортеж (с1, с2) уникален).


    Весь смысл в том что весь кортеж (с1, с2, c3, c4) находится в индексе, т.е. ему не нужно лезть в таблицу для проверки данных.


    А вообще-то, даже следующее будет с INCLUDE-индексом если не быстрее, то за то-же самое время:


    select ... where c1 = ?v1 and c2 >= ?v2fr and c2 <= ?v2to and c3 = ?v3 and c4 = ?v4

    Собственно по той же причине.
    По крайней мере для MSSQL проверялось мною не раз — чистый index-seek в обоих случаях.

  • Что нового в PostgreSQL 11: INCLUDE-индексы
    0
    1. Да
    2. Да, но смысл сомнителен при выборке по юник-ключам (c1, c2)
  • Что нового в PostgreSQL 11: INCLUDE-индексы
    0

    Заменяет два, потому что oldunqidx — UNIQUE и покрывает ключевые поля (и соответственно быстрее), кроме того играет дополнительно роль CONSTRAINT по кортежу (c1,c2);


    Собрав же только один индекс oldcvridx (даже если и UNIQUE, но уже по 4-м полям), вы "теряете" обе эти возможности.

  • Что нового в PostgreSQL 11: INCLUDE-индексы
    0
    порядок полей в Include неважен

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


    select c3, c4 from sometab where c1 = ?v1 and c2 = ?v2
    select c4, c3 from sometab where c1 = ?v1 and c2 = ?v2
  • Что нового в PostgreSQL 11: INCLUDE-индексы
    +11

    Нужно наверное добавить, что де факто — эта штука "слизана" с INCLUDE-INDEX for SQL Server от мелко-мягких… (которая по моему появилась в MSSQL аж в 2005-й версии).


    Реально полезная штука…
    И тут по моему не совсем понятно описаны преимущества сего действа — т.е. грубо говоря для чего оно вообще имеет место.
    В общем, вот это вот:


    CREATE UNIQUE INDEX newidx ON sometab (c1, c2) INCLUDE (c3, c4);

    заменяет следующие два индекса (в старом виде):


    CREATE UNIQUE INDEX oldunqidx ON sometab (c1, c2);
    CREATE        INDEX oldcvridx ON sometab (c1, c2, c3, c4);

    без хранения редундантной "дубликации" для одинаковых значений.


    Т.е. прирост скорости тут скорее вторичен (например через меньшее вымывание кэша на соответственно меньшем индексе и за счет меньших потерь времени на перестроение его на CUD-операциях).


    Например, для этого примера (если все c1-c4 int):


      Name    | RowCnt  | Reserved | Data     | IndexSize | Unused
      ------- | ------- | -------- | -------- | --------- | ------
    - testold | 638976  | 49112 KB | 15832 KB | 33192 KB  | 88 KB
    + testnew | 638976  | 35472 KB | 15832 KB | 19560 KB  | 80 KB

    Про скорость оно всё сложно на самом деле, но если тупо в лоб при прочих равных (под паразитной нагрузкой) — как-то так:


    # 1M rows
    - testold:  365.057 µs/# 2740 # 2739.3 #/sec
    + testnew:  357.219 µs/# 2800 # 2799.4 #/sec
    # 10M rows
    - testold:  413.326 µs/# 2420 # 2419.4 #/sec
    + testnew:  367.916 µs/# 2719 # 2718.0 #/sec
    # 100M rows
    - testold:  696.943 µs/# 1435 # 1434.8 #/sec
    + testnew:  455.329 µs/# 2197 # 2196.2 #/sec

    Ну и при таком "сахаре" бонусом сверху возможность использовать короткий UNIQUE индекс по значениям c1, c2 при scan по короткому кортежу (как в этом примере и др. тому подобные вещи).

  • Continuous Integration для новичков
    +2
    # get previous best results:
    wget .../my-srv/my-url/best-results.txt
    # measure previous:
    git checkout %{previous}%
    my-prog-perf-tests > before.txt
    # measure current:
    git checkout %{current}%
    my-prog-perf-tests > after.txt
    # create diff's between both versions:
    diff -u before.txt after.txt > test-perf.diff
    diff -u best-results.txt after.txt > test-perf-rel-best.diff

    Получаем что-нибудь вида test-perf.diff, ну и дальше травим это какому-нибудь анализатору:


    # analyze:
    my-perf-analyser -best best-results.txt -prev 1 < test-perf.diff > analysis.txt
    my-perf-analyser -best best-results.txt < test-perf-rel-best.diff >> analysis.txt
    # out in log of CI:
    cat analysis.txt
    # out the best-results back to the server:
    curl -F "file=@best-results.txt;filename=best-results" .../my-srv/my-url

    На самом деле вариантов очень и очень много...

  • Continuous Integration для новичков
    +3
    это практика разработки программного обеспечения, которая заключается в слиянии рабочих копий в общую основную ветвь разработки несколько раз в день...

    Вот как раз слияние то при CI совершенно не обязательно. И тот же травис умеет например как отдельные ветки так и PR и иже с ними "исполнять".
    CI помогает написать сценарий для автоматической "сборки", и исполнить его многократно на "чистой" системе, с компиляцией под разные компиляторы (например gcc/clang), исполнением на разных версиях интерпретаторах (python2.x, python3.x, pypy и т.д.), прогоном тест-кейсов (для разных целевых параметров), проверкой покрытия кода (aka code-coverage) и еще кучей всего — чего разработчик и/или тестер желают на него навесить (например сборкой чего-нибудь с опцией типа "mem-debug" для проверки на memory leaks после исполнения тестов, или проверкой на подключение к "чужому" коду, если то модульно и т.д.).
    Особливо дотошные товарищи умудряются даже проверку скорости исполнения (сравнение результатов до/после) воткнуть.


    Собственно слияние рабочих копий в общую основную ветвь — это, ИМХО, совершенно вторично здесь.

  • Массивы, указатели и другие квантовые явления вокруг нас
    0
    Совершенно верно...,
    более того если развернуть это, чтобы однозначно не нашел (добавить после table чего-нибудь, обнулить, убрав padding/alignment), например как здесь — gcc 7.x все-равно его «найдет».
    Хотя gcc trunk уже «поумнел».
  • Массивы, указатели и другие квантовые явления вокруг нас
    0
    Оптимизировать до границы массива (т.е. выкинуть из цикла проверку на индексах 0..1), а на UB (при нахождении out-of-range)…
      1. честно проверять далее.
      2. оптимизировать как получится (но желательно бы с одинаковым результатом от версии к версии) и кидать варнинг (что есть очень и очень просто на константных то индексах).
  • Массивы, указатели и другие квантовые явления вокруг нас
    0
    На случай если тот линк протухнет:
    static int table[2];
    static int exists_in_table(int v) { 
      int i;
      for (i = 0; i <= 2; i++) { 
        if (table[i] == v) return 0; /* found */
      }
      return 1; /* not found */
    }
    
    int main() {
       return exists_in_table(42);
    }
    

    gcc 4.6.x — gcc 6.x
    main:
      mov eax, 1
      ret
    

    gcc 7.x — gcc trunk
    main:
      xor eax, eax
      ret
    
  • Массивы, указатели и другие квантовые явления вокруг нас
    0

    Когда однажды (давным давно) мир UB сказал мне "Здравствуй и добро пожаловать", я тогда подумал, что наверно не просто так в C для возврата используют 0 в качестве OK, а всё остальное как другие состояния (например кода ошибок)…
    Ну и я для себя решил, что раз при большинстве UB оно редко возвращает 0 (типа "позитивный" исход как OK), то лучше всё же придерживаться того же… Вплоть до того, что и в C++ в качестве return больше не юзал true/false (а 0/1), хотя там всё чуть сложнее. Ну и стиль определённый при написании выработался. Плюс асёрты/тест-кейсы там и всё такое.
    Я вроде знаю что UB, знаю что вроде бы не определено, но карты так часто складываются… Как они с-ка "понимают", где positive а где negative case, остаётся загаткой, но так уж они себя ведут… Вели...


    Потому что потом с далёкого севера пришел белый пушной зверёк вышел gcc 7.x, который с-ка перевернул "привычный" мир позитив/негатив исходов при UB и всё сломал а я потом долго искал, как с этим боротся.
    Хотя бы вариант был бы чтоб оно хоть варнингом кидалось (ибо у меня всегда везде -Werror), но это же "мы сильно много хотим"...


    Так и живем теперь… как на пороховой бочке :)

  • Hessian-Free оптимизация с помощью TensorFlow
    0

    Ну вот вам универсальный HF для theano…
    Блэкбоксед обернутый, т.е. "просто" добавь воды определить и пробросить cost-функцию.
    В работе видел, не то что бы в восторге (но я предвзят ибо и theano не люблю), но достаточно интересно.
    Ну а на уровне просто "включить" оно работать никогда не будет, имхо...

  • Hessian-Free оптимизация с помощью TensorFlow
    +1
    Вообще-то HFO это, в теории, способ избежать vanishing-проблемы градиента, возникающие как раз при обратном распространении (backpropagation). Насколько я вижу, в статье речь идет про прямое распространение.

    Для глубокого обучения с SGD удается избежать этой проблемы изменяя настройки обучения и/или «глубоким» тюнингом архитектуры, так что…
    В конце концов всё сводится тупо к сравнению между сложностью построения конкретных моделей сети (и выбора стратегий), как-то предварительный тюнинг и т.д. и собственно HFO.
    Пока не (или не совсем) в пользу последней, и хотя HFO еще не достаточно хорошо изучена, уже есть куча исследований на эту тему, где в некоторых редких случаях она лучше, в остальных же — сильно нет.
    Вроде бы HFO пока наиболее хорошо себя показала на рекуррентных, типа elman-based без LSTM и подобным им.
    Хотя я где-то (вроде даже на github) видел нормально работающую DQN с LSTM слоями использующую HFO, но…

    SGD по-прежнему впереди планеты всей, хотя и не без недостатков. До тех пор, пока кто-то не найдет лучший, не градиентный, способ. HFO это в общем-то просто еще одно предложение из многих, и пока что еще далеко не панацея, и возможно ошибаюсь, еще долго не будет считаеться ею.
  • #PostgreSQL. Ускоряем деплой в семь раз с помощью «многопоточки»
    0

    Да запросто… было так… лет десять назад.


    Кстати, насчет "съедет план", у union как правило он много стабильнее (даже через вью).
    Я даже ранее какой-нибудь "поехавший" на OR-IN план union-ами лечил.
    Т.е. когда вот это вот:


    select * from MT t ...
    where t.somefield in (select x.field1 from XT x where $criteria1)
    or t.otherfield in (select x.field2 from XT x where $criteria2)
    -- ready, 5172 ms

    заменялось на:


    select * from MT t ...
    where t.somefield in (select x.field1 from XT x where $criteria1)
    union all
    select * from MT t ...
    where t.otherfield in (select x.field2 from XT x where $criteria2)
    -- ready, 31 ms

    Оно еще как-то понятно.


    Но когда такое же случалось, просто на большой выборке с OR по нескольким полям (1 к 1, без full-scan, сложных join и т.д.)…
    Какого спрашивается.

  • #PostgreSQL. Ускоряем деплой в семь раз с помощью «многопоточки»
    +3

    Немного оффтоп: а зачем так мигрировать вообще? В смысле, вы про "прозрачную миграцию" что-нибудь слышали?
    Т.е. собственно процесс "миграции" происходит постепенно (on-the-fly, application-assisted), используя новые классы данных и небольшой background сценарий вызовов сверху:
    типа while not ready: get(oldset) + set/alter-update(newset) + del(oldset).


    Т.е. чтение реализуется в виде:


    dataset GetSomeEntry(...) {
      // read dataset (from new-table)
      ...
      // if does not exists - try to read from old-table
      GetSomeEntry_MIG(...)
      ...
      // read child items:
      if (dataset.version < version.current) {
      //... use old api ...
      } else {
      //... use new api ...
      }
      ...
    }

    Если язык реализации приложения — скриптовый, то оно инжектами/обёртками на стадии загрузки приложения легко реализуется...


    Запись только новым API, в новом формате (в новые таблицы/структуры).


    А остальное (типа выборки и т.д.) оборачивается view (если необходимо) и/или сливом bulk-ом в materialized/temporary-table в новом формате.


    А так всё последовательно в два шага, например:


    1. правкой всех forign constraint/trigger, переименованием таблицы sometable в sometable_mig, созданием новой sometable_new, c начальным identity равным max(sometable_mig.id) и вьюхой sometable:


      create view sometable as 
      -- simulate new table using old table:
      select ... from sometable_mig
      union all
      select * from sometable_new

      Ну или наоборот табличкой sometable и view sometable_migview, зависит от условий, например сколько в кодовой базе обращений к sometable не "обернутых" переменными, и/или соотношение insert/delete к select/join (хотя постгрес умеет updatable view и подобные конструкции позволяющие прозрачную миграцию)...


    2. по полному завершению процесса "миграции" (хоть через неделю — месяц), вторым шагом, удалением view sometable, пустой таблицы sometable_mig, и конечным переименованием таблицы sometable_new в sometable.
      И накатывания "чистой" кодовой базы, уже без инъекций типа
      if (dataset.version < version.current) {...}

    Transparent migration позволяет выкатить обновление приложения без миграции, полностью перелопатить просто гигантские базы, практически совсем без отрыва (т.е. hot), без длинных транзакций, с одним WAL (без плясок с бубном вокруг репликации, не трогая ее вовсе) и на 90% используя новый (готовый) API приложения (ну и обернутый практически теми же тестами, что и основной функционал).

  • #PostgreSQL. Ускоряем деплой в семь раз с помощью «многопоточки»
    0

    А как вы думаете, что случится при миграции а то и откате (после ошибки) одной большой, нет "гиганской" транзакцией, т.е. если без штук типа ихней "многопоточки"…
    Даже умолчим про autovacuum, immutable states, пересбор индексов/статистик и т.п. прелести и сопутствующие эффекты на такой длинной транзакции и огромной базе...


    Так мигрировать на горячую не есть камильфо...


    Хотя если нужно таки всё неразрывно под DDL, то обычно морозят states (PITR, снапшоты и т.п.), многопоточно сливают изменения в новые таблички, а потом апдейтят/сливают bulk-ом в одной транзакции, и если все без остановки (aka hot), то сверху накатывают изменения из states(point_after — point_before), WAL по PITR и т.п… А так вообще очень сильно зависит от ситуации/требований (например, я утрирую, всё много сильно сложнее, если миграция базы длится неделю и размер diff-а для последующего обновления настолько огромен, что время накатывания оного снова приближается к той же неделе).


    Ну и бэкапы никто еще не отменял...

  • Введение в Postman
    0
    Ну строго говоря, чтобы делать «нормальный» автомат (тестовый стенд) на SoapUI, с вот-этим всем типа CI, CLI (command line), сценариями и мокапами нужен уже SoapUI Pro, который вовсе не бесплатен…
  • Оптимизация кода в уме, или «Ну так же однозначно быстрее»
    0
    Кто-то — это на минуточку профессор (в UNC)..., про «умнее» компилятора — это думаю однозначно (по крайней мере Дон уж точно их не одну тонну перелопатил вдоль и поперёк)..., сделал он этот «фикс» походя (не сильно напрягаясь сам, и вряд ли напрягая команду — ибо конкретно такие «обфускации» даже новички читают бегло)..., и результат вовсе не однозначно предсказуем/очевиден.
    Т.е. напрасно — да, ИМХО возможно даже показательно (в качестве примера, отсюда статья).
    Однако это писалось однозначно не для того, что бы кого-то тыкать носом.

    В общем кто-то мог просто пройти мимо, не оставляя таких «капитанских» и очень содержательных комментариев.
    П.С. Ну и наверно стоит всё же немного уважительней относится к людям, тратящим своё время и нервы на опенсорс…
  • Оптимизация кода в уме, или «Ну так же однозначно быстрее»
    0
    > И даже на Skylake может до 4 циклов занимать.

    2-operand form, при умножении на 0/1? Вы серьезно?

    > Я, наверное, ничего не понимаю в колбасных обрезках

    Наверное… :) выше под умножением понималось умножение в сишном коде, как его уже реализует компилятор не очень интересно.

    Конкретно в контексте того упомянутого `switch`, ужо не упомнить (а думать некогда), но чисто для примера:
    ```asm
    ; в EAX передается значение для switch-а…
    ; дефоулт всё что больше 50, размер каждой ветки (паддинг) = 24
    cmp EAX, 50
    ja switch_default
    imul EAX, const_padding_size ;# EAX *= 24
    jmp EAX
    sw0th:
    ...; instr (24 bytes)
    sw1st:
    ...; instr (24 bytes)
    sw2nd:
    ...; instr (24 bytes)

    sw50th:
    ...; instr (24 bytes)
    switch_default:
    ret
    ```
  • Оптимизация кода в уме, или «Ну так же однозначно быстрее»
    0
    Проблема в том, что умножение — весьма дорогая операция.

    Да ну? Тот же imul в интелях всего с максимально 3 cycle latency если мне не изменяет память.
    А условный переход, он как привило длиннее (в реальности).


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


    Просто он забыл, что компиляторы давно и буквально следуют первому правилу при процессорной оптимизации (машинного кода):


    Always avoid a branch if you can.

    Т.е. что условный переход на таком коротком if тоже не получится...


    Ну и еще забылось что имеем: branch prediction / ILP, instruction reordering, instruction, TLB and/or data cache (hits/misses/page faults) т.д., и register renaming и прочее впридачу.
    Работать компилятором нынче очень сложно. :)


    Так где оно может, хотя бы теоретически, иметь смысл???

    Я видел вполне себе хорошую реализацию switch на imul для коротких выравненных кусков кода. Даже очень. Побило всё остальное, вплоть до многоуровневых jump-tables, и прочие дериваты.
    Другое дело что оно, так-то, не универсально конечно.


    И не забывайте, что кэш процессора ограничен. Часто Ofast оптимизация, создающая код чуть длиннее чем O2, много быстрее на искусственных тестах, пока в бою не проявляются проблемы на multithreading, паразитной нагрузке и т.п.

  • Оптимизация кода в уме, или «Ну так же однозначно быстрее»
    0

    Здесь конкретно да, а в других примерах ещё как посмотреть...


    Про "более навороченным компиляторам" тоже могу поспорить.
    Оно местами настолько "навороченно", что неявное (а то и неопределённое) поведение на нормальном течении словить можно (было как-то, долго боролся, помог откат на пред. версию).


    Из последнего вот к примеру, expressive diagnostics у них вообще таким местом реализован, что варнинг на варнинге и третьим погоняет (даже без "-Wextra"). А если например в проекте варнинг к ошибке преравнивается?

  • Оптимизация кода в уме, или «Ну так же однозначно быстрее»
    0
    не настолько компиляторы глупы, как sebres их пытается выставить.

    А нельзя ткнуть носом, где я пытаюсь их такими выставить?


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


    И потом я же написал — "во всех вариантах (и даже с максимальной оптимизацией) test1 ничем не лучше, а то и проигрывает test2".


    Про собственно clang же много историй можно рассказывать. Он у меня был любимый долгое время… даже кастомная собственная сборка с измененным поведением при оптимизации.
    Потом я столько всего под clang словил, что окончательно забросил...

  • Оптимизация кода в уме, или «Ну так же однозначно быстрее»
    0
    да разве то анализ… то просто один коммит, по моему неплохо подходящий в качестве примера
  • Оптимизация кода в уме, или «Ну так же однозначно быстрее»
    –5
    В чём проблема инициализировать index сразу значением opnd

    Как раз это компилятору все равно, а в такой форме оно нагляднее, и речь тут не о том… Да и в оригинальной функции оно не так...


    но при этом именно это и делаете в test2.

    Совершенно нет, и при "ассемблерном мышлении" как раз проще — результат присвоения в eax, потом cmp eax, и условное действие (переход или присвоение-пересылка).


    Все дело в том, что условный переход действие не дешевое, и раньше их часто заменяли, умножением в том числе...

  • Оптимизация кода в уме, или «Ну так же однозначно быстрее»
    –5
    там у вас не стояло слово «лишний“ разве? если нет, тогда звиняйте (уже перебрал значит)…
    Только умножение он хотел вместо условного перехода (то что вы назвали „оператор ветвления“), так что — ваше „ещё и“ все равно мимо.
  • Оптимизация кода в уме, или «Ну так же однозначно быстрее»
    –7
    операторы сложения? где? между константами? учить мат-часть…