Как стать автором
Обновить
19
0
Evgeny Astigeevich @eastig

Пользователь

Отправить сообщение

Можно ссылки на разоблачения? Выборочно посмотрел лекцию. То что услышал, встречал в книгах, например Body By Science и ряде других англоязычных. Часть вещей из лекции согласуются с моим личным опытом и более 10 лет наблюдений в спортзале. Например, люди посещающие в основном кардио классы и работающие там в полную силу, так и не избавились от жировой прослойки и не получили рельефные мышцы.

:) Там скорее смесь "доброй" и "недоброй" воли.
Наша команда в Unipro (контрактора Sun) участвовала в разработке Java Compatibility Kit. Без прохождения JCK нельзя было использовать Java в названии software. Microsoft хотел быструю Java на Windows и него была JVM 1.1, но она не проходила все тесты JCK.
В те времена Sun был сказочно богат и считал, что Windows это скорее враг чем друг, что пользователи Windows не приносят существенного дохода. Основной платформой для Java, Sun считал SunOS/Solaris. Вместо того, чтобы договориться и улучшить Java, Sun решил наказать Microsoft. Наша команда предоставила доказательства для суда. Только для Sun это была пиррова победа, которая привела к тому, что Java ушла с desktop на server. Умер J#, зато родился C#.

Я был в Apache Harmony с его начало. Кстати, IBM был ключевым участником в проекте Harmony. Sun не давал JCK, поэтому Apache Harmony не могла использовать Java в названии. Нам инженерам, Intel продавал светлое будущее Apache Harmony. В конце стало понятно, что основной целью Intel было усилить свои позиции в сегменте серверов. Java быстро набрала популярность в разработке enterprise приложений, а для таких приложений нужны мощные сервера :) Серверная Java была в основном не на Intel серверах, потому что Sun Java была не оптимизирована под x86. У Sun не хватало ресурсов на это, что в итоге привило к приобретению Hotspot.

Когда у Sun начались проблемы с продажей SPARC серверов, он обратил свое внимание на x86. Тут обнаружилось, Sun Java позади IBM J9 и BEA JRockit. Sun из врага Intel, стал партнером. Наша команда в Intel работала над улучшением производительности Sun Java. Другая часть людей из Harmony работала на портированием Sun Java на Itanium. Потом был проект оптимизации Android Runtime(ART) для x86.

В общем в этой истории были свои скандалы и интриги :)

Спасибо, Валера, за сохранение памяти об этих и других событиях. Хоть что-то останется записанным.
Как участник тех событий: Unipro_Sun -> Intel_Harmony -> Intel_Sun -> Intel_VIP, подтверждаю - веселые были времена.
VIP был очень интересным проектом. Его ISA был взрыв мозга. Особенно отладка assembler программ :)
А performance analysis так вообще был на уровне magic. Часть людей осела в Arm.

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

double calc_prob(int i, double p) {
   if (i == 1)
     return p;
   return p*(calc_prob(i-1, p) + calc_prob(i-1, 1-p));
}

double prob_kill = calc_prob(5, 0.2) + calc_prob(5, 0.8) - pow(0.8, 5);

Странно, у меня на ARM64 этот код дает неправильный результат. Вот такой код работает:


  begin = clock();
  min = 1e200;
  int64_t min64 = to_int64(min);
  next = 1;
  long j = -1;

  for (long i=0; i<size; i++) {
    // next = 1./(next+1);
    int64_t x = to_int64(gig[i]);
    if (x < min64) {
      min64 = x;
      j = i;
    }
  }
  end = clock();

Результат:


3GB random doubles generated
next: 1.000000e+00 min: -1.797693e+308 time: 0.725408
next: 1.000000e+00 min: -1.797693e+308 time: 0.511060

Можно переименовать статью: ускорения поиска минимального числа в массиве вещественных чисел.
Но как только в цикле появится переход от целого к вещественному, то все ускорение пропадет.

А можно ассемблерный код?

Потому что GCC предполагает, что для работы с double будут использоваться в основном FP инструкции, что в целом правда. Так как целочисленных регистров всегда не хватает, компилятор старается использовать все другие регистры.
Кстати в коде для x86_64, значения также пересылаются из FP регистров XMM в целочисленные регистры. И это код сгенерированный clang.

AArch64, Neoverse N1


$ gcc --version
gcc (GCC) 7.3.1 20180712 (Red Hat 7.3.1-12)
$ gcc -O3 test.c
$ ./a.out
3GB random doubles generated
next: 6.180340e-01 min: -1.797693e+308 time: 2.417564
next: 6.180340e-01 min: -1.797693e+308 time: 2.417601
$ gcc -O3 test_nodiv.c
$ ./a.out
3GB random doubles generated
next: 1.000000e+00 min: -1.797693e+308 time: 0.725358
next: 1.000000e+00 min: -1.797693e+308 time: 1.451623

Получается, что нативная реализация в 2 раза быстрее.
Ассемблерный код:


.L6: // цикл с нативным сравнением
    ldr d0, [x21, x0, lsl 3]
    add x0, x0, 1
    fcmp    d0, d8
    fcsel   d8, d8, d0, pl
    cmp x0, x1
    bne .L6
...
.L8: // цикл с is_smaller
    ldr d0, [x21, x0, lsl 3]
    fmov    x1, d8
    add x0, x0, 1
    fmov    x3, d0
    asr x2, x1, 63
    eor x2, x1, x2, lsr 1
    asr x1, x3, 63
    eor x1, x3, x1, lsr 1
    cmp x2, x1
    fcsel   d8, d8, d0, le
    cmp x0, x4
    bne .L8

Видно, что в цикле с is_smaller нам приходится пересылать значения из FP регистров D0/D8 в целочисленные регистры X1/X3. Цикл с is_smaller содержит в 2 раза больше инструкций.

Сомнительное преимущество:


  1. FPU большую часть времени простаивают, так как количество целочисленных инструкций заведомо больше. Если только это не в ручную написанный код.
  2. Пересылка данных между целочисленными регистрами и FP регистрами не бесплатно, на ARM'ах 2-3 такта.

Есть у вас результаты бенчмарок, показывающие преимущество вашего подхода?

В ARM AArch64 есть инструкции специально для этого: FCMP и FCM*, которые исполняются за 2-3 такта: https://godbolt.org/z/cr4Mcq
На x86_64 — UCOMISD.

На самом деле, большинство задач, включая design interview, которые дают на собеседованиях в FAANG не такие уж и сложные. Думаю где-то 99% тех что мне давали. Да был 1% задач, которые были реально сложные. Вся проблема заключается в стрессе. Как только человек научится контролировать стресс, он успешно будет проходить любые интервью при условии наличия нормальных технических способностей. К сожалению нет silver bullet как держать под контролем этот стресс. Каждый должен найти свой метод.


На мой взгляд, составляющие успеха:


  • умение преодолевать стресс: 30%
  • хорошее знание английского языка и умение ясно коммуницировать: 30%
  • технические навыки решения задач: 25%
  • хорошее резюме: 10%
  • везение: 5%

Хочу поделиться своим опытом прохождения собеседований в Google (2 неудачных onsite), Facebook (1 неудачное onsite, несколько заваленных скрининг), Apple (несколько заваленных скрининг) и Amazon (2 onsite, одно заваленное скрининг).


Выпусникам вузов и Juniors, и в какой-то степени Middles, проще пройти собеседования чем Seniors, так как у них проверяют только основные навыки: основы CS, способность решать задачи и коммуницировать решение. Им больше прощают ошибки. У них только одна проблема — это, чтобы их заметили и пригласили на собеседование. Просто так отправка резюме в компании вряд ли поможет. Здесь сильно помогает посещение конференций, знакомые, особенно linkedin, стажировка в крупных компаниях. Им как раз сильно должны помочь всякие LeetCode и книжки про прохождение собеседований. Чаще всего их собеседуют без особой связи с позицией на которую подался человек.


От Seniors ожиданий больше, особенно Design Interview. Оно будет практически одним из самым главных критериев оценки. Seniors будут стараться задать как можно больше вопросов разной сложности. Поэтому очень важно уметь быстро писать код при недостатке времени. Как только код написан и доказана его корректность, начинается процесс обсуждения того как его можно улучшить. Чаще всего это и есть главный этап собеседования. Если все время ушло на написание и отладку и не хватило на обсуждение, то результат скорее всего будет негативный. Для Seniors больше шансов пройти интервью, если опыт в резюме пересекается с позицией, на которую собеседуют. Все мои попытки пройти собеседования на Generally Smart Software Engineer, провалились практически после пары первых раундов. Собеседования на позиции, где мой опыт был бы полезен, практически все заканчивались onsite интервью. Процесс подготовки Seniors отличается от процесса подготовки Juniors/Middles и занимает минимум три месяца. Оптимально — шесть. От книжек пользы не много, особенно от всюду рекламируемой Cracking the Coding Interview. За время ее существования вышла куча статей в Интернете с ее пересказом. Так что проще прочитать пару-тройку этих статей. Все другие книги пишутся как под копирку. Для подготовку к Coding Interview, я рекомендую книги по спортивному программированию. Мне больше всего помогла Guide to Competitive Programming: Learning and Improving Algorithms Through Contests. LeetCode полезен только в начале, для выработки и поддержания навыка решения задач. Больше месяца-двух тратить на него смысла нет. Можно стать умельцем решения задач LeetCode. Процесс решения задач на интервью все таки отличается. И да, не нужно ставить цель прорешать и запомнить все задачи. От этого пользы мало, так как задач очень много и их решения невозможно запомнить. Интервальные методы запоминая тут не помогут.


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


Полезно проходить собеседования в разные компании, для тренировки. Вот тут независимые рекрутеры могут быть полезны, так как они подготовят список таких компаний и быстро сведут с ними. Только не проговоритесь, что это вам для тренировки. Эти собеседования вам помогут улучшить коммуникационные навыки и стрессоустойчивость. Особо не надейтесь что они помогут вам подготовиться к техническим интервью FAANG.


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


Onsite интервью — это тоже лотерея, но уже с большей вероятностью выйгрыша.


Будьте готовы к встрече с людьми с завышенным чувством собственного значения. Таким людям не нравится, когда ответ не совпадает с тем, что они хотят услышать. К счастью таких людей попадается очень мало. По большей части собеседования, особенно onsite, в FAANG оставляют приятные впечатления.


Очень помогает понимание того, что процесс собеседования в FAANG, нацелен прежде всего на минимизацию найма некомпетентного сотрудника. То что вы не прошли, еще не значит, что у вас больше нет шансов попасть в FAANG. Я в итоге прошел собеседования в Amazon и принял офер.


Если есть вопросы, спрашивайте, буду рад ответить.

В бытность, когда был вовлечен в разработку ARMCC 6, у LTO была проблема удаления символов, которые линкер посчитал ненужными, но они на самом деле нужны. Если это этот случай, то нужно поиграть с опциями линкера developer.arm.com/documentation/101754/0615/armlink-Reference/armlink-Command-line-Options/--lto-keep-all-symbols----no-lto-keep-all-symbols
Еще можно поиграть с developer.arm.com/documentation/101754/0615/armlink-Reference/armlink-Command-line-Options/--lto-level
Это затруднительно сделать в силу большого разнообразия версий Android и производителей телефонов.
 Например исправили security bug в Java core или framework библиотеках. Насколько я помню любое изменение в системных компонентах требовало перекомпиляции всех приложений, но могу и ошибаться.
Кстати, в ART JIT-компилятор и AOT-компилятор — это один и тот же компилятор, который запускают либо в режиме JIT или AOT. AOT-компилятор можно запустить через утилиту dex2oat.
В статье не говорится, почему вернулись к схеме Interpreter+JIT+AOT. Основная проблема с AOT была, что при любом изменении системы приходилось перекомпилировать все библиотеки и приложения, что могло занимать много времени. При переходе на Interpreter+JIT+AOT одним из критериев был не ухудшение времени запуска. После перехода выяснилось, что не весь код приложений нужно компилировать.

В ART применяется многократная AOT перекомпиляция кода в зависимости от изменения профиля исполнения. Кроме того Google Play может предоставлять некий профиль исполнения приложения, который учитывается при установке приложения.

В Android 10 и 11 случился APEX. Теперь ART может обновлять через Google Play, если производитель телефона поддерживает эту функцию.
В теории может, но на практике я этого в LLVM не видел.

что LIR load при кодогенерации на АРМе может распадаться на ldr,ldp,ld1,ld2,ld3,ld4 вас не убеждает


Такие вещи могут делать в LLVM backend'е, где оперируют MIR (https://llvm.org/docs/MIRLangRef.html).
Вначале MIR стараются получить как можно близко похожим на LIR. И он неоптимален. Затем этот MIR прогоняют через кучу оптимизаций, где могут делать свёртки/разбивки инструкций (strength reduction/peephole optimizations). Затем MIR трансформируют в MachineCode, который также прогоняют через оптимизации. И эти оптимизации пишутся под конкретный target ISA, где уже оперируют в терминах инструкций ISA.
Цепочка преобразований: LIR-MIR(здесь очень похожи на LIR)->MachineCode(здесь уже все дальше от IR)->Assembly
LLVM позволяет быстро создать кодогенератор с помощью TD файлов, где описывается mappping MIR в Target ISA. Так как этот кодогенератор сгенерированный, то он просто мепит одни инструкции на другие без особого анализа и обработки. Поэтому можно утверждать что исходный IR отображается практически один в один в target ISA.
Если в вашу ISA так просто IR не отобразить, то тогда нужно будет писать такое отображение ручками, где каждая инструкция MIR как-то сложно преобразуется.
LLVM разрабатывался таким образом, чтобы IR максимально легко было отображать на target ISA.
Я помню как мы добавляли ARMv8.x расширения к LLVM. На первом этапе — это просто создание td файлов описаний. Затем мы реализовывали специфичные оптимизации, и то если в этом есть необходимость.

Информация

В рейтинге
Не участвует
Откуда
Cambridge, England - East, Великобритания
Зарегистрирован
Активность