LINUX.ORG.RU

Избранные сообщения gentoo_root

USB Wi-fi адаптер с поддержкой Linux Libre (свободные драйверы)

Форум — Linux-hardware

Здравствуйте!

Я пользуюсь GNU/Guix на ядре LinuxLibre, потому что он работает без сбоев, легко откатиться в случае неудачного обновления, пакеты которые включены в систему хорошо ладно работают, ну и это безопасне, чем проприетарщина.

И мне нужно выбрать usb wi-fi адаптер, который можно купить в магазине в моем городе (магазин ДНС).

Подскажите, какие адапетры нормально поддерживаются?

Тут не могу сопоставить https://wireless.wiki.kernel.org/en/users/drivers с тем, что есть в магазине.

Atheros нет в этом магазине. Мне импонирует Zyxel и Asus:

  • Wi-Fi адаптер ASUS USB-N10 Nano
  • Wi-Fi адаптер ASUS USB-N13
  • Wi-Fi адаптер ZyXEL NWD6505
  • Wi-Fi адаптер ZyXEL NWD6605
  • Wi-Fi адаптер ASUS PCE-AC51

На сайте h-node.org присутствуют адаптеры с протоколом 802.11(a)b/g/n, 802.11a, 802.11n. А поддержки 802.11ac нет.

Упомянутые USB-адаптеры поддерживают протокол 802.11b/g/n, но остаётся вопрос, действительно ли они поддерживаются в LinuxLibre?

# cat /proc/version
Linux version 5.2.6-gnu (nixbld@) (gcc version 7.4.0 (GCC)) #1 SMP 1

 , ,

znavko
()

LineageOS 15.1, Moto Z2 play (albus)

Форум — Mobile

4pda не очень поэтому закидываю на ЛОР пусть будет здесь возможно кому поможет.

ЛОР и автор поста не несем ответственности за все, что может случиться с вашим телефоном в результате ваших действий. Вы делаете это на свой страх и риск и берете на себя ответственность.

Далее я буду описывать исключительно только то что использовал конкретно я и чем решал те или иные проблемы а так же о плюсах и минусах если таковые будут замечены. И да здесь будет только самое главное без воды.

Итак:

  • Само тело: аппарат Moto Z2 play (albus) модель XT1710-09 тип M274D сразу с дефолтной проблемой стоковой прошивки - неработающим сканером очепятка пальца совмещенным с кнопкой (далее по тексту кнопка) которая вылечивается вот так. Делал практически как описано за исключением очистки /data мне лень было тратить время на лишний бекап и восстановление. После заливки описанной версии прошивки и первого включения у меня кнопка не завелась. Завелась после первой же перезагрузки. И нет одного fastboot flash fsg fsg.mbn мне не хватило видимо трабл там глубже.
  • recovery: twrp_albus_treble_3.2.2_r23_64.img из минусов заметил только то что сжатие не работает оно печально ну да и ладно не больно то и надо.
  • Boot logo ставил Z2_Play_bootlogo_moto_flashable.zip оттуда как выглядит можно посмотреть там.
  • У прошивки LineageOS на данном аппарате тоже есть свой прикол. Видимо наличие той самой кнопки заставило надмозги выпилить кнопки навигации полностью. Решение есть там если кратко то qemu.hw.mainkeys=0 добавить в /system/build.prop и перезагружаемся.
  • Протухшую radio фирмварь обновлял оттуда ALBUS_RETAIL_8.0.0_OPSS27.76-12-25-11_cid50_subsidy-DEFAULT_regulatory-DEFAULT_CFC.xml.zip вот так
    fastboot flash modem NON-HLOS.bin
    fastboot erase modemst1
    fastboot erase modemst2
  • Далее на очереди Magisk. Крайний magisk на крайней версии прошивки у меня завёлся без проблем. f2fsfix не ставил и Xposed мне тоже без надобности. Клиент банка на букву с завёлся и работает а вот проверку SafetyNet пока успешно пройти не удалсь. Не помог MagiskHide Props Config.

Оставшиеся вопросы:

  • Существует ли в природе более вменяемая версия twrp recovery под albus?
  • Можно ли заставить работать дефолтную moto boot logo без чёрных екранов? Уж больно она торт.
  • Зачем в LineageOS 15.1 не нужно это новое TV App? Знающие скажите что это за ненужно и если это работает то где?
  • Ну и как бороть SafetyNet в Magisk на LineageOS 15.1?

 , magisk, ,

init_6
()

Аргумент «мне нечего скрывать»

Форум — Talks

Часто вижу аргумент «мне нечего скрывать», когда обсуждаются проблемы ИБ и методы работы спецслужб (читай государства) с гражданами (как реально применяемые, так и потенциально возможные). Вот тут http://tehlug.org/files/solove.pdf даны очевидные контраргументы на «мне нечего скрывать»:

Ответы на утверждение «мне нечего скрывать»:

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

2) мне не нужно оправдываться, что мне нечего скрывать, бремя доказательства обратного лежит на стороне обвинителя, если хотите что-то узнать, приходите с ордером;

3) мне нечего скрывать, но и нет желания вам что-то раскрывать;

4) если вам нечего скрывать, вы не живёте полноценной жизнью;

5) (государству) покажите то, что скрываете вы, и тогда я раскрою свою информацию;

6) дело не в том, что нечего скрывать, а в том, что нечего совать нос в чужие дела;

7) «мне нечего скрывать» означает «мне всё равно, что кто-то суёт свой нос в чужие дела, пока это не касается лично меня»;

8) Ответ на «законопослушным гражданам нечего скрывать»: неприкосновенность частной жизни по определению подразумевает право гражданина скрывать компрометирующую его информацию — не важно, скрывает ли он какое-то нарушение или нет.

seiken
()

Модульный роутер

Форум — Talks

Теперь роутер можно собирать из кусочков:

https://www.lupa.cz/aktuality/cz-nic-chysta-novy-turris-router-ma-byt-modular...

Перемещено leave из general

 ,

Jopich1
()

О неопределённом поведении и багах оптимизатора clang на примере разбора цикла статей Криса Латтнера, разработчика clang.

Форум — Development

про ud2 - лень читать комменты - но кто-то должен был оставить вот этот цикл из трех постов:

http://blog.llvm.org/2011/05/what-every-c-programmer-should-know.html
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_14.html
http://blog.llvm.org/2011/05/what-every-c-programmer-should-know_21.html

stevejobs, спасибо за ссылки. С интересом почитал. Ответ получился довольно длинным, даже движок форума не хочет принимать его в таком виде в качестве простого камента, поэтому я решил, что он тянет на отдельную тему. Тем более, что здесь разбирается не какой-то мелкий баг/фича clang'а, а общий подход к созданию оптимизатора, основанный на изложении и анализе статей одного из разработчиков этого компилятора Криса Латтнера (Chris Lattner). Ну и ещё мне пришлось полностью переписать один из его примеров, чтоб он начал работать и иллюстрировать излагаемые им идеи. Если хочешь, можешь послать ему код, чтоб вставил в свою статью вместо своего, не рабочего. Я не возражаю.

А для тех, кто не в теме, это продолжение темы Вызов никогда не вызываемой функции.

Основная мысль автора цикла статей, как я понял, выражена ближе к концу 3-ей статьи в короткой фразе:

c) is a lot of work to implement.

Т. е. автор, по сути, соглашается, что они реализовали какую-то дичь с этими оптимизациями, объясняя некоторые причины: что де оптимизатор не знает, что на входе получает компилятор и даже не знает, что получает он сам на предыдущем проходе, ну и некоторые другие причины. А в конце говорит: но переделывать эту неудачную архитектуру нам лень, поэтому пользуйтесь тем, что есть. Что ж, fixed. В любом случае, статьи полезны, т. к. проливают свет на реальное (и довольно печальное) положение дел, связанных с оптимизациями в компиляторе clang.

Теперь разберу примеры из статей.

1. В первом примере автор пытается показать, почему к указателю на int нельзя обращаться как к указателю на float:

float *P;
 void zero_array() {
   int i;
   for (i = 0; i < 10000; ++i)
     P[i] = 0.0f;
 }

int main() {
  P = (float*)&P;  // cast causes TBAA violation in zero_array.
  zero_array();
}

Этот код — полная дичь. Он будет вылетать и с оптимизациями, и без них, потому что в переменную P (которая по умолчанию инициализируется 0), записывается её собственный адрес, а дальше, начиная с этого адреса, записываются ещё 40000 байт, которые непременно выдут за границы выделенной памяти.

Я немного переделал этот пример, чтоб он заработал, добавив сразу после P массив достаточного размера, в который и будут записываться числа (тоже undefined, но по факту работает с обоими компиляторами — clang и gcc), и заменив запись 0 на запись адреса &P+1, для чего ввёл объединение ufp, т. к. иначе на первой же итерации P будет указывать на 0, после чего на 2-й итерации произойдёт сегфолт. Ну и ещё добавил printf'ы для вывода информации и return, как того требует gcc и стандарт. Тут же отмечу, что мне пришлось слегка повозиться с unsigned *p, объявленным внутри функции print_array(). Сначала я сделал его глобальным, объявив до указателя float *P, и получил похожий на приведённый, но не совсем верный вывод: вместо ожидаемого 0x601268, 0x0, 0x0, 0x601268 программа без оптимизаций выдавала 0x601268, 0x0, 0x601268, 0x0. После установки watchpoint'а в дебагере выяснилось, что массив повторно модифицируется функцией print_array(). Просмотр адресов глобальных переменных &P и &p показал, что и clang, и gcc вставляют p после P и перед массивом arr, хотя в тексте программы она была объявлена первой. Видимо, компиляторы зачем-то сортируют переменные по типам и располагают указатели на float раньше указателей на unsigned. После переноса unsigned *p внутрь функции, всё стало работать, как и ожидалось. Вот мой рабочий (хоть и намеренно некорректный) вариант:

#include <stdio.h>

float *P;

float arr[10000];

union ufp
{
  float** p; float f;
} fp={&P+1};

void zero_array() {
   int i;
   for (i = 0; i < 10000; ++i)
     P[i] = fp.f;
 }

void print_array() {
   int i;
   unsigned *p;
   printf("&P==%p, P==%p\n", &P, P);
   for(i = -2; i < 10000; ++i)
    {
      p=(unsigned*)P;
      printf("&P[%i]==%p, P[%i]==%f (%p: 0x%X)\n", i, &P[i], i, P[i], p+i, *(p+i));
    }
}

int main() {
  P = (float*)&P;  // cast causes TBAA violation in zero_array.
  zero_array();
  //P=(float*)(&P+1); // restoring P for optimizer
  print_array();
  return 0;
}

При компиляции clang'ом без оптимизации:

clang -o zero_array zero_array.c

этот вариант выдаёт следующее:

&P==0x601260, P==0x601268
&P[-2]==0x601260, P[-2]==0.000000 (0x601260: 0x601268)
&P[-1]==0x601264, P[-1]==0.000000 (0x601264: 0x0)
&P[0]==0x601268, P[0]==0.000000 (0x601268: 0x0)
&P[1]==0x60126c, P[1]==0.000000 (0x60126c: 0x601268)
&P[2]==0x601270, P[2]==0.000000 (0x601270: 0x601268)
&P[3]==0x601274, P[3]==0.000000 (0x601274: 0x601268)
&P[4]==0x601278, P[4]==0.000000 (0x601278: 0x601268)
[skip]
&P[9994]==0x60ae90, P[9994]==0.000000 (0x60ae90: 0x601268)
&P[9995]==0x60ae94, P[9995]==0.000000 (0x60ae94: 0x601268)
&P[9996]==0x60ae98, P[9996]==0.000000 (0x60ae98: 0x601268)
&P[9997]==0x60ae9c, P[9997]==0.000000 (0x60ae9c: 0x601268)
&P[9998]==0x60aea0, P[9998]==0.000000 (0x60aea0: 0x601268)
&P[9999]==0x60aea4, P[9999]==0.000000 (0x60aea4: 0x601268)

и корректно завершается.

Если же включить оптимизацию:

clang -o zero_array -O2 zero_array.c

то получаем следующее:

$ ./zero_array
&P==0x601260, P==0x60126800601268
Ошибка сегментирования

Кстати, такой же результат будет, если откомпилировать эту программу компилятором gcc с включённой оптимизацией (там только адреса будут немного другими). Избавиться от этой ошибки можно 2 способами:

  1. Закомментировав вызов print_array() в функции main().

    Очевидно, что в этом случае никакого вывода мы не получим.

  2. Раскомментировав в main() строчку
    P=(float*)(&P+1); // restoring P for optimizer

    Тогда мы получим такой вывод:

    &P==0x601260, P==0x601268
    &P[-2]==0x601260, P[-2]==0.000000 (0x601260: 0x601268)
    &P[-1]==0x601264, P[-1]==0.000000 (0x601264: 0x0)
    &P[0]==0x601268, P[0]==0.000000 (0x601268: 0x601268)
    &P[1]==0x60126c, P[1]==0.000000 (0x60126c: 0x601268)
    &P[2]==0x601270, P[2]==0.000000 (0x601270: 0x601268)
    &P[3]==0x601274, P[3]==0.000000 (0x601274: 0x601268)
    &P[4]==0x601278, P[4]==0.000000 (0x601278: 0x601268)
    [skip]
    &P[9994]==0x60ae90, P[9994]==0.000000 (0x60ae90: 0x601268)
    &P[9995]==0x60ae94, P[9995]==0.000000 (0x60ae94: 0x601268)
    &P[9996]==0x60ae98, P[9996]==0.000000 (0x60ae98: 0x601268)
    &P[9997]==0x60ae9c, P[9997]==0.000000 (0x60ae9c: 0x601268)
    &P[9998]==0x60aea0, P[9998]==0.000000 (0x60aea0: 0x0)
    &P[9999]==0x60aea4, P[9999]==0.000000 (0x60aea4: 0x0)
    

Проблема тут очевидна: в цикле в P[i] записывается адрес &P+1. Но указатель P указывает на самого себя благодаря присвоению P = (float*)&P. Соответственно, элемент P[0] находится по тому же адресу, что и P. Когда при 1-й итерации цикла мы записываем туда адрес следующего элемента, указатель P меняется. В 64-битной ОС размер указателя равен 8 байтам, а размер float — 4, т. е. P у нас теперь указывает на начало arr. Дальше мы записываем 1-ый элемент от нового начала массива, т. е. по сути 3-й элемент, пропуская таким образом 2 элемента.

Когда же мы включаем оптимизатор (и в clang, и в gcc), он записывает все двойные слова подряд, начиная с 0-ого (в P[-1] у нас 0 потому, что мы перезаписали его после вызова zero_array(), чтобы программа не вылетела при вызове print_array()). Поэтому в первых 2 элементах у нас записано число 0x601268 (если представлять его как беззнаковое целое длиной в 4 байта), но 1-ые 2 элемента одновременно являются адресом, на который указывает P, т. е. адресом 0x0060126800601268 (0x601268 повторенное 2 раза). Если ничего не выводить, то всё тоже проходит успешно. Но как только мы вызываем print_array() (не модифицировав этот дикий адрес), программа сразу пытается отобразить содержимое не валидного адреса 0x601268, а того самого 0x0060126800601268, которого в нашем адресном пространстве просто нет. И получает сегфолт.

Почему printf отображает значения с плавающей точкой, которые в целочисленном виде выглядят как 0x601268, нулями, а не NAN, как по идее должно бы было быть, я не знаю. Видимо, это баг стандартной библиотеки (надо будет послать багрепорт, если никто мне не объяснит, что они правы).

Кстати, оба компилятора по неведомым мне причинам при оптимизации (а я пробовал разные уровни оптимизации) почему-то вместо записи поля fp.f memset'ом продолжают генерить цикл, только более короткий, чем без оптимизации (ассемблерные листинги я тут приводить не буду, кому интересно, могут сами откомпилировать с опцией -S). Хотя при записи константы 0 компилятор clang с вкючённой оптимизацией вместо цикла вызывает memset (gcc и в этом случае генерит цикл).

На всякий случай укажу версии использованных компиляторов:

$ clang --version
Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0)
Target: x86_64-pc-linux-gnu
Thread model: posix

$ gcc --version
gcc (Debian 4.9.2-10) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.
Это свободно распространяемое программное обеспечение. Условия копирования
приведены в исходных текстах. Без гарантии каких-либо качеств, включая 
коммерческую ценность и применимость для каких-либо целей.

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

c) is a lot of work to implement.

Такие они, разработчики clang'а.

Но идею я понял: при заполнении массива 0 или другими значениями в цикле, опасно одновременно менять указатель на этот массив. Но при чём тут изначальное утверждение о том, что

It is undefined behavior to cast an int* to a float* and dereference it (accessing the «int» as if it were a «float»).

Как это утверждение иллюстрируется данным примером?

Я уже не говорю о том, что оптимизировать циклы в memset нет никакой необходимости, потому что программист и сам может это сделать, сократив не только получившийся бинарник, но и исходник. А если программисту до этого нет дела, то почему компилятору должно быть дело? Тем более, если программист сделал цикл намеренно, то компилятору совсем незачем это исправлять. Думаю, именно поэтому gcc и не сворачивает циклы в memset. Я уже не говорю о том, что если уж вы сворачиваете их в memset, то будьте последовательны. Почему при заполнении массива константой 0 вместо цикла clang вызывает memset, а при заполнении того же массива одной не меняющейся переменной длиной в 4 байта оставляет цикл? Грош цена такой оптимизации.

Вот заменить вызов memset на ассемблерную команду rep stos действительно было бы полезно, но почему-то ни clang, ни gcc этого не делают.

2. Во втором примере автор цикла показывает, как смертельный указатель может запутать оптимизатор clang так, что тот сгенерит очередную фигню вместо исполняемого кода. Вот пример смертельного кода из 2-й статьи:

void contains_null_check(int *P) {
  int dead = *P;
  if (P == 0)
    return;
  *P = 4;
}

Очевидно, что если передать функции contains_null_check() NULL, то код будет непереносимым (undefined behavior). В защищённом режиме при попытке разыменования такого указателя произойдёт сегфолт. (UPD: практически аналогичная ошибка в ядре Linux 2.6.30 и 2.6.18 для Red Hat привела к серьёзной уязвимости, причём при разыменовании указателя система не падала.) Однако в реальном режиме такой код вполне законный. Более того, если мы рассматриваем язык си как системный язык, то в некоторых случаях без подобного кода в реальном режиме не обойтись. Что у нас лежит по адресу 0 в реальном режиме? — Указатель на обработчик 0-ого прерывания (деление на 0). А что если я хочу зарегистрировать свой обработчик? Для этого и существует неопределённое поведение: в одних системах оно работает так, а в других иначе. Но разработчики clang'а считают, что «неопределённое поведение» — это индульгенция на генерацию разного бреда вместо нормального кода.

Но вернёмся к статье. Автор описывает 2 варианта поведения оптимизатора.

  1. В первом варианте сначала проверяется избыточный код, а затем избыточные проверки. Выглядит это примерно так:
    void contains_null_check_after_DCE(int *P) {
      //int dead = *P;     // deleted by the optimizer.
      if (P == 0)
        return;
      *P = 4;
    }
    

    На этом этапе совершенно справедливо выпилили переменную dead, т. к. она нигде не используется.

    Далее идёт проверка избыточности проверок и делается правильный вывод о том, что проверка P на равенство 0 нужна. Она остаётся. Всё работает, как и задумывалось (и даже не падает в защищённом режиме на радость быдлокодерам).

  2. Во втором варианте оптимизатор сначала проверяет проверки программиста на избыточность, а затем выпиливает ненужные переменные:
    void contains_null_check_after_RNCE(int *P) {
      int dead = *P;
      if (false)  // P was dereferenced by this point, so it can't be null 
        return;
      *P = 4;
    }
    

    Здесь оптимизатор почему-то решил, что раз *P разыменовывается без проверки, то он априори 0 быть не может и проверять его необходимости нет. А то, что программист мог ошибиться, разработчикам оптимизатора даже в голову не приходит. Как и то, что помимо защищённого режима есть ещё и реальный. А бывают ещё компиляторы для разных контроллеров и встроенных специализированных систем, где разыменовывать 0 указатели бывает нужно и иногда даже необходимо. Или clang такие системы не поддерживает? И никогда не сможет поддержать с подобным подходом, ориентированным на работу только защищённых многозадачных ОС.

    Но вернёмся к статье. На следующем этапе выпиливается переменная dead и проверка на 0 и остаётся:

    void contains_null_check_after_RNCE_and_DCE(int *P) {
      *P = 4;
    }
    

    Если раньше программа корректно работала в реальном режиме, а в защищённом падала, то теперь в реальном режиме вектор 0-ого прерывания перезаписывается адресом 4. В результате при любой ошибке деления компьютер намертво зависает (хотя реальный режим clang, как я понимаю, не поддерживает и никогда не сможет поддержать с таким шикарным легаси).

3. Третий пример я разбирать не буду, т. к. согласен с автором, что оптимизация «x > x+1 всегда false» может быть полезна при использовании макросов. А для проверки переполнения существуют константы MAX_*.

4. Четвёртый пример — почти из поста Вызов никогда не вызываемой функции. Его уже разобрали по полочкам, сломали все копья, какие только можно было сломать, в т. ч. и я, поэтому здесь повторяться не буду. Единственно, скажу, что мне было непонятно, зачем заменять вызов функции по 0-ому адресу с неизбежным сегфолтом на недопустимую инструкцию ud2. Автор поясняет во 2-й статье:

2. Clang has an experimental -fcatch-undefined-behavior mode that inserts runtime checks to find violations like shift amounts out of range, some simple array out of range errors, etc. This is limited because it slows down the application's runtime and it can't help you with random pointer dereferences (like Valgrind can), but it can find other important bugs. Clang also fully supports the -ftrapv flag (not to be confused with -fwrapv) which causes signed integer overflow bugs to trap at runtime (GCC also has this flag, but it is completely unreliable/buggy in my experience). Here is a quick demo of -fcatch-undefined-behavior:

В вольном пересказе: мы всегда так делаем, чтобы показать, что код содержит участки с неопределённым поведением. И плевать, что недопустимая инструкция не указывает на некорректный код. Просто ничего лучшего мы не придумали.

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

И напоследок 2 эпические цитаты. Первая из начала 1-ой статьи. Она очень понравилась dzidzitop:

It turns out that C is not a «high level assembler» like many experienced C programmers (particularly folks with a low-level focus) like to think

Вот оно что оказывается. Си — это та же ява, чуть более быстрая и более опасная. А для написания системных вещей переходите на настоящий ассемблер! Кен Томпсон гомерически хохочет и Деннис Ритчи переворачивается в гробу.

А вторая из 3-ей, заключительной статьи:

Ultimately, undefined behavior is valuable to the optimizer because it is saying «this operation is invalid - you can assume it never happens».

В вольном пересказе это обозначает: «Вау! Неопределённое поведение! Ворочу куда хочу!»

UPD: Вот хочу добавить сюда ещё несколько ответов на вопросы, на которые приходится отвечать по всему треду одно и то же:

1. То, что ub обозначает «делай, что хочешь!», мягко говоря, неправда. Вот, что написано в стандарте C99:

3.4.3

1 undefined behavior

behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements

2 NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

3 EXAMPLE An example of undefined behavior is the behavior on integer overflow.

Т. е. в стандарте чётко прописаны 3 действия, из которых разработчики компиляторов могут выбрать любое:

1. Игнорировать ситуацию. Смотрим в Ожегове, что обозначает слово «игнорировать»:

Умышленно не заметить, не принять во внимание.

Т. е. «игнорировать» — это сделать вид, что всё нормально и пройти мимо, а не модифицировать или удалять такой код, и уж тем более делать на его основе какие-то бредовые предположения.

2. Компилировать и выполнять такой код в соответствии с документацией, с выводом предупреждающих сообщений или без них. Т. е. напишите явно в документации, что если мы встречаем 0 указатель, то делаем то-то и то-то, и делайте. Но не в тихую.

3. Прерывать компиляцию и/или выполнение с обязательным выводом диагностических сообщений.

И всё. Ни о каком «что хочешь» в стандарте речи не идёт. Вот тут мне в каментах подсказали, что «with unpredictable results» обозначает «что хочешь». Но на самом деле это обозначает лишь то, что результаты могут быть непредсказуемыми, а совсем не то, что компилятор может делать всё, что угодно (хотя разработчикам таких компиляторов подобная трактовка очень удобна).

Ну и тот же человек считает, что «это notes», а значит неважно, что там написано. Но т. н. неопределённое поведение при переполнении целого — вообще example из того же пункта:

EXAMPLE An example of undefined behavior is the behavior on integer overflow.

И больше я нигде никаких упоминаний об ub при арифметическом переполнении не нашёл. Про переполнение при сдвигах — нашёл. А в других случаях — нет. Но все почему-то на этот example ссылаются.

2. Многие говорят, что быдлокодеры должны страдать. Но серьёзные уязвимости, связанные с ub, а точнее с непредсказуемой реакцией компилятора на ub, в разное время обнаруживались в ядре Linux, во FreeBSD и в GDK-Pixbuf, затрагивающая Chromium, Firefox и VLC. Подробнее см. в этом комментарии, чтоб не раздувать и без того длинный верхний пост. Здесь только скажу, что уязвимость в ядре Linux связана с ошибкой, идентичной со 2-м примером из разбираемых статей.

3. Автор статей и многие в этом треде утверждают, что автоматически отыскать такие ошибки очень сложно и дорого, а то и вовсе невозможно. Но это тоже не так. В Интернете я нашёл такой пример си++ программы с ub:

#include <iostream>
int main()
{
    for (int i = 0; i < 300; i++)
        std::cout << i << " " << i * 12345678 << std::endl;
}

Программа из-за переполнения временного результата на 174-й итерации при использовании ключа оптимизации -O2 в g++ попадает в бесконечный цикл.

Запустив компиляцию, я получил следующие предупреждения (причём безо всяких опций -W что-то_там):

$ g++ -o infinity_loop -O2 infinity_loop.cpp
infinity_loop.cpp: В функции «int main()»:
infinity_loop.cpp:5:38: предупреждение: iteration 174u invokes undefined behavior [-Waggressive-loop-optimizations]
         std::cout << i << " " << i * 12345678 << std::endl;
                                      ^
infinity_loop.cpp:4:5: замечание: containing loop
     for (int i = 0; i < 300; i++)
     ^

А ведь здесь случай куда менее очевидный, чем простое разыменование NULL-указателя.

4. Наконец, на Хабре я вычитал, что стандартный макрос

#define offsetof(st, m) ((size_t)(&((st *)0)->m))

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

UPD 2: Вот тут Sorcerer в комментарии кинул ссылку на письмо Линуса Торвальдса в рассылке от 12 января 2009 года, где он пишет о том, что думает о некоторых оптимизациях. Приведу несколько фрагментов этого письма в своём переводе:

Type-based aliasing — это тупость. Это такая невероятная тупость, что даже не смешно. Оно испорчено. И gcc взял испорченную концепцию и настолько её раздул, следуя букве-закона, что получилась бессмысленная вещь.

[skip]

Это НЕНОРМАЛЬНО. Это так невероятно безумно, что люди, которые делают это, просто должны избавиться от своего убожества, прежде чем они смогут восстановить. Но реальные gcc программисты действительно думали, что это имеет смысл, потому что стандарт это позволяет и даёт компилятору максимальную свободу, — потому что он может делать теперь вещи БЕЗУСЛОВНО АБСУРДНЫЕ.

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

[skip] И если кто-то жалуется, что компилятор невменяемый, компиляторщики скажут «ня, ня, разработчики стандарта сказали, что так можно», с абсолютным отсутствием анализа, имеет ли оно СМЫСЛ.

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

[skip]

Угадайте, что произойдёт, если вы имеете такой безумный склад ума и пытаетесь сделать безопасный код без alias'а, — вы займёте лишнее пространство на стеке.

По факту, Linux использует -fno-strict-aliasing из-за чертовски веской причины: потому что в gcc понятие «strict aliasing» является огромной зловонной кучей д-рьма. Linux использует этот флаг не потому, что Linux исполняется быстро и свободно, он использует этот флаг, потому что _не_ использует тот безумный флаг.

Type-based aliasing неприемлемо тупо для начала, и gcc вознёс этот идиотизм до совершенно новых высот, фактически не обращая внимания даже на статически видимый aliasing.

Линус

Оригинал (на английском):

( читать дальше... )

И ещё спасибо anonymous'у за камент с ещё одним сообщением на ту же тему того же автора от 26 февраля 2003 года.

Ну и от себя добавлю, что не только Линусу не нравится aliasing. Microsoft тоже не спешит реализовывать его в своём Visual C++. Т. е. не нравится это тем, кто помимо разработки компиляторов создаёт и другой софт с использованием этого компилятора, например ОС. А те, кто создают только компиляторы для сферических программистов в вакууме, рьяно эту фичу реализуют, хоть их и никто не заставляет.

Ну и напоследок оставлю несколько полезных ссылок на память:

Стандарт C11 (последний) (pdf), Стандарт C99 (pdf),

http: //read.pudn.com/downloads133/doc/565041/ANSI_ISO%2B9899-1990%2B%5B1%5D.pdf (Стандарт C89) (pdf),

http: //web.archive.org/web/20030222051144/http: //home.earthlink.net/~bobbitts/c89.txt (Стандарт C89) (txt),

https: //web.archive.org/web/20170325025026/http: // www .open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4660.pdf (Стандарт C++17) (последний) (pdf),

Стандарт C++14 (pdf), Стандарт C++11 (pdf),

бумажный перевод стандарта C++17, выполненный Зуевым и Чуприновым, Москва, 2016, на основе Working Draft, Standard for Programming Language C++ от 22 мая 2015 года (номер документа n4527) за 4945 руб. (надеюсь, что эту ссылку не сочтут за рекламу, т. к. к авторам я никакого отношения не имею), а здесь можно скачать начало перевода (предисловие и содержание), ну и ещё торрент-ссылку видел на эту книгу, но здесь её публиковать не буду,

статья на Хабре (из песочницы) от 2014 г. Неопределенное поведение в C++, ещё одна статья там же от 2016 года Находим ошибки в коде компилятора GCC с помощью анализатора PVS-Studio, Разыменовывание нулевого указателя приводит к неопределённому поведению и Про C++ алиасинг, ловкие оптимизации и подлые баги. Это так, ссылки на заметку.

Некоторые ссылки парсер ЛОР'а не принял, поэтому мне пришлось разделить их пробелами, превратив в текст, который можно скопировать в адресную строку браузера, удалив пробелы. Там, где http встречается дважды в 1 строке — не ошибка, а именно такие ссылки.

 , , , ,

aureliano15
()

DIY «Собери свой роутер»

Галерея — Скриншоты

На фото самосборный роутер. Стоит матплата из серии pc engines, 2 mpcie модуля Mikrotik для обеспечения wifi сети 5Ghz и 2.4 Ghz. Загружается и работает на openwrt ( хотя любой линукс поддерживается тоже ). Из напильника - пришлось просверлить 3 доп. отверстия для антенны ( непонятно почему не сделали это по умолчанию ). Как бонус можно добавить еще 2 ethernet порта через mcpie карту.

Цена получилась немного больше стоимости топовых роутеров.

>>> Просмотр (1139x873, 1791 Kb)

 

Jopich1
()

Небольшой тест try_catch на C++, C, Vala

Форум — Development

Решил поделиться результатами.

Процессор, AMD FX 8350, 4Ghz

Компиляторы:

gcc version 7.2.0 (Ubuntu 7.2.0-1ubuntu1~16.04)
Vala 0.36.8

C/C++, без try catch

const char* noexcept_thrower_c(int i)
{
    if (i == 0)
        return "error";
    return NULL;
}

int noexcept_try(int i)
{
    int res;
    if (noexcept_thrower_c(i) == NULL)
    {
        res = 0;
    }
    else
    {
        res = 1;
    }
    return res;
}
C++ try..catch
void thrower_cpp(int i)
{
    if (i == 0)
        throw std::runtime_error("error");
}

int cpp_try(int i)
{
    int res;
    try
    {
        thrower_cpp(i);
        res = 0;
    }
    catch(const std::exception&)
    {
        res = 1;
    }
    return res;
}
Cexception Try..Catch
void thrower_c(int i)
{
    if (i == 0)
        Throw("error");
}

int cexception_try(int i)
{
    int res;
    CEXCEPTION_T e = CEXCEPTION_NONE;
    Try
    {
        thrower_c(i);
        res = 0;
    }
    Catch(e)
    {
        (void)e;
        res = 1;
    }
    return res;
}
Vala try..catch
public errordomain Error
{
    Thrower,
}

void thrower(int i)  throws Error
{
    if (i == 0)
        throw new Error.Thrower ("error");
}

int vala_try(int i)
{
    int res;
    try
    {
        thrower(i);
        res = 0;
    }
    catch(Error e)
    {
        (void)e;
        res = 1;
    }
    return res;
}
Получившиеся результаты:
vala_try                                 3 ns/op
vala_catch                             252 ns/op
c++_try                                  1 ns/op
c++_catch                             2382 ns/op
noexcept_try                             1 ns/op
noexcept_catch                           1 ns/op
сexception_try                           9 ns/op
сexception_catch                        25 ns/op
Ничего неожиданного, но меня порадовал с++ когда входим только в try, действительно zero-cost exception. Так же несколько удивило время vala, при входе в catch.

Добавил исходники на github: https://github.com/fsb4000/try_bench

 , ,

fsb4000
()

Посоветуйте что-то селфхостовое совместимое с Android на замену гуглоконтактам.

Форум — General

Продолжают периодически пропадать гуглоконтакты под Android. Особенно бесит то, что я эти контакты бережно переносил и пополнял с девайса на девайс аж с 2001-го года и никогда раньше потерь не было. А теперь даже не знаешь, всё ли на месте. Вот понадобилось сейчас позвонить человеку, а его нигде нет. Ни на коммуникаторе, ни в Gmail...

Соответственно, ищется локалхостовая альтернатива с клиентом синхронизации под Android. Чтобы умел произвольные наборы телефонов, ФИО, как полные, так и не полные, поля под разные IM, аватарку...

Есть такое в природе?

 , ,

KRoN73
()

Skyhost skype API

Форум — Mobile

Обнаружил, что в maemo skype сделан по принципу шифрованного статического бинарника skyhost и привязанного к maemo UI. Есть так же readme, в котором указано, что рядом должен быть обазец использования skyhost API на C++. Связь происходит через socket, поддерживается видеосвязь.
На моей gentoo пока не удалось заставить работать UI. Показывает пустое окно и пишет binary corrupted, после чего зависает, но скорее всего оно связано с теми return 0, которые я сделал на libconic и osso.
Существование статического skyhost под разные архитектуры может позволить сделать более открытый и лёгкиц вариант skype. Но это имеет смысл только если протокол skyhost не сломан. На maemo он ещё работает?


Half-life 2 не занимаюсь т.к потерял mmc с отладочным glibc, а на сборку куча времени нужна.

mittorn
()

XDG Base Directory Specification, даже когда софт не хочет.

Галерея — Скриншоты

Довольно давно меня подзадолбала мусорка в домашней директории, постепенно получилось заставить почти весь софт гадить в строго определенное место, а именно в .config, .cache и .local

Для особо одаренных (Skype, Dropbox) пришлось слегка поизвращаться, если для Skype достаточно было изменить параметр запуска на

skype --dbpath=$HOME/.local/share/skype
, то для Dropbox уже пришлось городить костыль в виде

HOME=$HOME/.local/share/dropbox /usr/bin/dropbox start -i 2>&1

Остальной софт относительно разумен, где через alias, где через export, удалось обяснить, куда складировать свое добро. Ниже листинг .bashrc и .profile, авось кому пригодится.

( Листинг )

>>> Просмотр (749x517, 36 Kb)

 

gwinn
()

warning: char ** -> const char *const *

Форум — Development
void f(const char *const *a) {}

int main(void)
{
	char **a;
	f(a);
	return 0;
}
kotik@kotik-laptop:/tmp:0> clang test7.c 
test7.c:6:4: warning: passing 'char **' to parameter of type 'const char *const *' discards qualifiers in nested pointer types
      [-Wincompatible-pointer-types-discards-qualifiers]
        f(a);
          ^
test7.c:1:27: note: passing argument to parameter 'a' here
void f(const char *const *a) {}
                          ^
1 warning generated.

Так и должно быть? Почему?

 , ,

Kotolegokot
()

pulseaudio + systemd

Форум — Desktop

Как-то было дело поставил pulseaudio и оно заработало 'изкоробки'. Потом заметил, кода переключаешься между пользователями — звук есть только у одного — почитал http://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/Perfec..., удалил пользователей из группы audio — всё заработало.
Вчера, вдохновившись этим тредом Всё, Поттеринг победил решил поставить попробовать systemd :). Немного помучился, но всё запустил, что надо, грузится, работает нормально... вроде бы на первый взгляд.
Запускаю плеер — не играет. Звука нет.
Запускаю alsamixer — там с громкостью всё нормально, смотрю по F6 звуковую карту — один дефоулт.(обычно там в списке ещё intel hda).
Покопался по настройкам пульсы/альсы — вроде всё в норме.
Убил пульсу (killall -9 pulseaudio) убил иксы, запускаю в консоли alsamixer — intel hda видит, музыку играет. Запускаю иксы( в .xinitrc поставлено start-pulseaudio-x11) — звук пропал :).
Ок. добавляю себя в группу audio, перелогиниваюсь — запускаю иксы — всё нормально звук есть. Через альсу звук нормально идёт — через openAL(в q2pro попробовал) — рывками.
Вот такие, блины-пироги. Поделитесь собственным опытом пожалуйста. Чего я делаю не так? Есть какие-нибудь советы/предположения что это такое и как исправить это безобразие? Как настроить пульсу с системд, чтобы не добавлять пользователя в группу audio? Может какие демоны стартовать нужно?
Помогите:)

 , , , ,

Bad_ptr
()

ideapad. Нашёл способ управления зарядом батареи.

Форум — General

Привет, ребята.

У меня есть ноутбук Lenovo ideapad G580 (20150). И у этого ноутбука под венду есть утилита под названием «lenovo energy management». Среди возможностей этой утилиты есть и функция управления зарядом батареи - полный заряд и режим защиты аккумулятора. В Linux этой фичей пользоваться нельзя, нет средств для этого (tp_smapi и tpacpi-bat только для настоящих ThinkPad'ов). Меня этот факт очень огорчал и я провел изыскания в результате которых нашел способ переключения режимов батареи.

Вообще управляется эта фигня через Super_I/O, но не суть важно.

Для начала нам нужен оффтопик с установленным «lenovo energy management» и тулзой RWEverything.

Запускаем RWEverything и тыкаем иконку EC скрин. Переключаем в «lenovo energy management» режимы батареи и смотрим какой байт меняется в окошке «Embedded Controller». В моем случае это байт по адресу «0A», 21 - защита батареи, 41 - полный заряд. А EC_SC/EC_DATA это адреса регистров, которые нам потом понадобятся. Все ясно, перезагружаемся в линукс.

Сначала я хотел использовать superiotool, но фиг там:

# superiotool 
superiotool r6637
No Super I/O found

Однако удача была со мной, и я нашел fanctrl.c, который и послужил основой для моей поделки.

Собственно моя поделка:

#include <stdint.h>
#include <sys/io.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/* Поменяйте на свои значения */
#define EC_SC 0x66
#define EC_DATA 0x62
#define IBF 1
#define OBF 0
#define EC_SC_READ_CMD 0x80
#define EC_SC_WRITE_CMD 0x81
#define EC_SC_SCI_CMD 0x84
#define BATT_PORT 0x0a
#define BATT_LIMIT 0x21
#define BATT_FULL 0x41

static void init()
{
    if (ioperm(EC_DATA, 1, 1) != 0)
    {
        perror("ioperm(EC_DATA, 1, 1)");
        exit(1);
    }

    if (ioperm(EC_SC, 1, 1) != 0)
    {
        perror("ioperm(EC_SC, 1, 1)");
        exit(1);
    }
}

static void wait_ec(const uint32_t port, const uint32_t flag, const char value)
{
    uint8_t data;
    int i;

    i = 0;
    data = inb(port);

    while ( (((data >> flag) & 0x1) != value) && (i++ < 100) )
    {
        usleep(1000);
        data = inb(port);
    }

    if (i >= 100)
    {
        fprintf(stderr, "wait_ec error on port 0x%x, data=0x%x, flag=0x%x, value=0x%x\n", port, data, flag, value);
        exit(1);
    }
}

static uint8_t read_ec(const uint32_t port)
{
    uint8_t value;

    wait_ec(EC_SC, IBF, 0);
    outb(EC_SC_READ_CMD, EC_SC);
    wait_ec(EC_SC, IBF, 0);
    outb(port, EC_DATA);
    //wait_ec(EC_SC, EC_SC_IBF_FREE);
    wait_ec(EC_SC, OBF, 1);
    value = inb(EC_DATA);

    return value;
}

static void write_ec(const uint32_t port, const uint8_t value)
{
    wait_ec(EC_SC, IBF, 0);
    outb(EC_SC_WRITE_CMD, EC_SC);
    wait_ec(EC_SC, IBF, 0);
    outb(port, EC_DATA);
    wait_ec(EC_SC, IBF, 0);
    outb(value, EC_DATA);
    wait_ec(EC_SC, IBF, 0);
}

static void dump_all_regs(void)
{
    uint8_t val;
    int i;

    printf("EC reg dump:");

    for (i = 0x00; i <= 0xff; i++)
    {
        if ((i % 16) == 0)
        {
            printf("\n 0x%02x: ", i);
        }

        val = read_ec(i);
        printf("%02x ", val);
    }

    printf("\n");
}

static void set_value(const uint8_t value)
{
    uint8_t rval;

    rval = read_ec(BATT_PORT);
    printf("old value %02x\n", rval);
    write_ec(BATT_PORT, value);
    rval = read_ec(BATT_PORT);
    printf("new value %02x\n", rval);
}

int main(int argc, char *argv[])
{
    init();

    if (argc < 2)
    {
        dump_all_regs();
    }
    else
    {
        if (argv[1][0] == 'f')
        {
            printf("set full charge\n");
            set_value(BATT_FULL);
        }
        else if (argv[1][0] == 'l')
        {
            printf("set limited charge\n");
            set_value(BATT_LIMIT);
        }
        else
        {
            printf("unknown option\n");
        }
    }

    return 0;
}

А это её работа:

# acpi
Battery 0: Unknown, 60%
# ./a.out f
set full charge
old value 21
new value 41
# acpi
Battery 0: Charging, 61%, 00:01:23 until charged
# ./a.out l
set limited charge
old value 41
new value 21
# acpi
Battery 0: Discharging, 61%, 01:52:05 remaining
# acpi
Battery 0: Discharging, 60%, 01:49:36 remaining
# acpi
Battery 0: Discharging, 60%, 01:47:34 remaining
# acpi
Battery 0: Unknown, 60%

PoMbl4
()

NNLUG проводит семинар по Xorg, Wayland, Mir с прямой трансляцией.

Новости — Конференции и встречи
Группа Конференции и встречи

22 июня с 15:00 до 16:00 в стенах Нижегородского РадиоТехнического Колледжа пройдет семинар: «XOrg, Wayland, Mir. Будущее графической системы в Linux»

Посвящать нас в глубины графических систем и оконных менеджеров будет Сергей Бессонов aka Aceler.

Планируется прямая видео-трансляция в интернет по ссылке ниже

>>> Подробности и видео-трансляция

 , , , ,

gumanoed
()

Новый ноут. Не грузится Кубунту.

Форум — General

Вообщем мне попал вот такой ноут: http://rozetka.com.ua/lenovo_ideapad_z570_59_321657/p211632/

Я установил на него Кубунту, сначала параллельно с Виндой. Но почему-то не запустился граб... Я подумал, что какой то прикол из-за раздела для восстановления и тупо создал новую таблицу разделов. Увы ничего не поменялось - вместо загрузки ГРАБ чёрный экран на сек 10 и возврат в меню выбора носителя :(

Кстати когда я ставил Кубунту стартовое меню с выбором языка отсутствовало, вместо него на экране были какие-то полоски, поэтому нажал Ентер = получил английский (хотя и так бы его выбрал)...

DenisPA
()

Победа над скайпом

Галерея — Скриншоты

Вобщем, я устал от этой проклятой, ужасной иконки (которая, кстати говоря, зачем-то 24х24 вместо стандартных треевых 22х22), и с горя начал стучать по клавиатуре копытами.

В результате получилось нечто, приводящее мой трей в более-менее приятный вид и делающее меня счастливым. Увы, на клавиатурах в Эквестрии всего две клавиши: Ctrl+C и Ctrl+V, поэтому за качество извиняйте.

Иконки для своей темы тоже вышли не очень, но в последний момент пришел MiniRoboDancer и немного помог, сделав иконки терпимыми.

enjoy (github)

Надо бы еще ебилд выложить, но он все равно слизан с ебилда skypetab-ng, как и почти все остальное.

>>> Просмотр (1366x768, 208 Kb)

 , ,

derlafff
()

Производительность; илитный запил оптимальных реализаций и основы матчасти.

Форум — Development

Поглядел я тут на пацанов и увидел прогресс в их глазах. Поэтому я решил вести тут свой бложик, в котором я буду толкать матчасть, разбирать/разрушать всякие мифы и легенды, а так же их обсуждать с пацанами. Банить меня не надо - тут всё будет очень культурно.

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

Изначально я хотел написать про то: что такое бесплатные вычисления на примере is_range() + сумма елементов массива, но тут выявилась смешная особенность, поэтому пока без is_range().

Начнём с простого - сумма елементов(float) массива. Как написать её быстро? Обычный крестопоц сделает так:

auto summ = accumulate(begin(vec), end(vec), 0.)

Этот код выдаёт 5.6GB/s(мы всё бенчим в л1д 32килобайта массив). Казалось бы, если бы мы слушали всяких «гуру», которые нам говорят: accumulate() - оптимизирован, «ты что умнее создатели stl"а?», «конпелятор умнее тебе - сам всё делает оптимально», «руками что-то делать слишком сложно и не нужно» - то мы бы там и остались с этими 5.6ГБ, но мы пойдём дальше и поймём почему так, и является ли это тем, что намн ужно.

Но посмотрев на код - он не векторизован:

	addq	$4, %rdx
	vcvtss2sd	-4(%rdx), %xmm2, %xmm2
	vaddsd	%xmm2, %xmm1, %xmm1

Почему? Патамучто это основная флоатпроблема: Он не ассоциативен - флоат не имеет в себе точных представлений всех чисел входящих в диапазон его «представления» т.е. порядкопроблемы.

Поэтому конпелятор НЕ ВЕКТОРИЗУЕТ флоат по умолчанию, ну никак. Даже такую банальщину.

Для решения этих проблем - есть ключик -funsafe-math-optimizations, который входит в -ffast-math, который кладёт на точность при вычислениях. Добавив его мы получаем уже 44.9GB/s.

Но теперь мы получаем ещё одну проблему - надо думать: «как бэ сунуть эту ключик не повредив там, где этот ключик не нужен».

Поэтому ноцанам, которые хотят быстро и не хоятт рандомных жоп из-за тупости конпелятора - пишут всё руками. Допустим на той же сишке это пишется так:

double memadd_autovec(buf_t buf) { //5.609465GB/s, либо 44.969652GB/s с ffast-math
  float * it = buf_begin(buf), * end = buf_end(buf), summ = 0.;
  do {
    summ += *it++;
  } while(it != end);
  return summ;
}

double hsumf(__v8sf v) {
  return (v[0] + v[1] + v[2] + v[3] + v[4] + v[5] + v[6] + v[7]);
}

double memadd_vec(buf_t buf) { //45.652002GB/s и класть на ffast-math
  __v8sf * it = buf_begin(buf), * end = buf_end(buf), summ = {};
  do {
    summ += *it++;
  } while(it != end);
  return hsumf(summ);
}

Т.е. разницы никакой нет, кроме нужной нам реализации горизантального сложение вектора. Когда я говорил пацану: «векторную сишку для написания быстрого кода юзать намного проще, чем плюсы» - поцан нипонимэ, да и любые пацаны скажут - ну дак с -ffast-math оба выдают по 45гигов - нахрен эта сишка нужна?

А вот зачем:

double memadd(buf_t buf) { //132.878440GB/s
  __v8sf * it = buf_begin(buf), * end = buf_end(buf), summ = {};
  do {
    summ += *it++;summ += *it++;summ += *it++;summ += *it++;
  } while(it != end);
  return hsumf(summ);
}

Это называется пацанский анролл копипастой, а вот заставить конпелятор нормально что-то разанролить очень сложно.

Если бы мы слушали всяких «гуру», которые нам вещают: «анрол говно и не нужен» - мы бы так и седели с 45-ю гигами, а так мы сидим с 132.878440GB/s. Т.е. анролл нам дал немного не мало ~300%.

Но основная мысль, которую толкают всякие «гуру» - это не надо следить за тактами/считать такты и прочее. Но мы о5 сделаем наоборот и посмотрим что будет.

Т.к. наш юзкейс упирается на 99% в throughput и дёргается одна инструкция, то нам достаточно просто считать теоретическую производительность для моего камня. 4.5(частота камня)*8(т.е. у нас камень с avx, то там вектор 32байта, либо 8флоатов.)*1(throughput нашей инструкции - в данном случае vpaddps из интел мануала). Т.е. 36гигафлопс, либо ~144гига. Т.е. мы сняли овер 90% теоретической производительности - остальные 10% у нас ушли в наши циклы, всякие горизонтальные суммы вектора и прочее, ну и конечно же чтение данных из кеша.

Но самое смешное - на моём хасвеле умножение имеет throughput 0.5 - т.е. на хасвеле умножение быстрее сложения. Это новая забористая трава у интела.

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

Поэтому очень смешно слушать, когда какие-то пацаны говорят: «float point имеет такую же производительность как и инты» - нет, оно имеет такоу же производительность лишь по причине того, что на штеуде инты тормазят так же, как и float.

И чтобы окончательно в этом убедится - мы взглянем на fma(вариации умножения со сложением/вычитанем), которые имеют throughput 0.5 - да, да - на хасвеле умножение+сложение в 2раза быстрее просто сложения. Это уже не просто трава - это что-то принципиально новое.

У целочисленного сложения же throughput 0.5 и казалось бы, если мы поменяем в нашей функции float на int - у нас будет сложение работать в 2раза быстрее, но это не так. Оно выдаёт те же 130гигов, а почему?

Вообще у камня есть такая фича, допустим у нас:

add $1, %reg0//вот тут инструкция add залочит регистр reg0
add $1, %reg0//а эта инструкция уйдёт в лок до особождения предыдущей инструкцией регистра reg0

Чтобы такой жопы небыло - есть специальная фича:

add $1, %reg0//lock reg0
add $1, %reg0//И тут вместо того, чтобы уйти в лок - камень вместо reg0 даёт инструкции любой свободный регистр.

Эта фича называется прееименование регистров, либо как-то так - мне лень гуглить.

Дак вот штука в том, что фича работает через жопу. Мне лень читать мануал и искать почему так, но штука в том, что она ограничивает throughput. На умножении и целочисленном сложении она огранивает throughput c 0.5 до 1.

И вот я решил заюзать сложении через fma:

__v8sf fmaadd(__v8sf a, __v8sf b) {
  return _mm256_fmadd_ps(_mm256_set1_ps(1.), a, b);// a + b * 1. == a + b.
}

double memadd_fma(buf_t buf) {
  __v8sf * it = buf_begin(buf), * end = buf_end(buf), summ = {};
  do {
    summ = fmaadd(summ, *it++);
  } while(it != end);
  return hsumf(summ);
}

Но меня ждала жопа: 27.347290GB/s, причем не анролл и ничего не помогал. Я уж подумал, что мануал наврал, но позже до меня допёрло: у неё latency 5тактов и ((4.5×8)÷5)×4 ~= 29гигов - т.е. я получаю производительность с её latency, но какой жопой оно так?

Потом я вспомнил, что гцц гинерит анрольный код вида:

add $1, %reg0
add $1, %reg0
//а не
add $1, %reg0
add $1, %reg1

Т.е. на неё вообще не работает переименовывание регистров - и инструкции постоянно в локе. Я это проверил и оказался прав. Ну и я написал такой мемадд:


__v8sf fmaadd(__v8sf a, __v8sf b) {
  return _mm256_fmadd_ps(_mm256_set1_ps(1.), a, b);
}

inline void fma_10way_finality(__v8sf * cache, __v8sf * it, __v8sf * end) {
  switch(end - it) {
    case 8:
      *(cache + 7) = fmaadd(*(cache + 7), *(it + 7));
      *(cache + 6) = fmaadd(*(cache + 6), *(it + 6));
    case 6:
      *(cache + 5) = fmaadd(*(cache + 5), *(it + 5));
      *(cache + 4) = fmaadd(*(cache + 4), *(it + 4));
    case 4:
      *(cache + 3) = fmaadd(*(cache + 3), *(it + 3));
      *(cache + 2) = fmaadd(*(cache + 2), *(it + 2));
    case 2:
      *(cache + 1) = fmaadd(*(cache + 1), *(it + 1));
      *(cache + 0) = fmaadd(*(cache + 0), *(it + 0));
    case 0:
      break;
    default: error_at_line(-1, 0, __FILE__, __LINE__, "bad_aligned");
  }
}

double memaddfma_10way(buf_t buf) {
  __v8sf * it = buf_begin(buf), * end = buf_end(buf), summ = (__v8sf){};
  __v8sf * cache = (__v8sf[10]){{}};
  uint64_t i = 0;
  while((it += 10) <= end) {
    *(cache + i) = fmaadd(*(cache + i), *(it - i - 1));++i;
    *(cache + i) = fmaadd(*(cache + i), *(it - i - 1));++i;
    *(cache + i) = fmaadd(*(cache + i), *(it - i - 1));++i;
    *(cache + i) = fmaadd(*(cache + i), *(it - i - 1));++i;
    *(cache + i) = fmaadd(*(cache + i), *(it - i - 1));++i;
    *(cache + i) = fmaadd(*(cache + i), *(it - i - 1));++i;
    *(cache + i) = fmaadd(*(cache + i), *(it - i - 1));++i;
    *(cache + i) = fmaadd(*(cache + i), *(it - i - 1));++i;
    *(cache + i) = fmaadd(*(cache + i), *(it - i - 1));++i;
    *(cache + i) = fmaadd(*(cache + i), *(it - i - 1));++i;
    i = 0;
  }
  fma_10way_finality(cache, (it - 10), end);
  summ = (*(cache + 0) + *(cache + 1) + *(cache + 2) + *(cache + 3) +
	  *(cache + 4) + *(cache + 5) + *(cache + 6) + *(cache + 7) +
	  *(cache + 8) + *(cache + 9));
  return hsumf(summ);
}

Пришлось хреначить финалити, ибо тут «анролл» на 10, а почему на 10 - для максимального throughput"а - надо, чтобы каждый каждый регистр юзался через 5тактов - т.е. 10регистров.

И вся эта порятнка нужна для борьбы с тупостью конпелятора.

Это уже: 214.167252GB/s(раельно там в районе 250 - просто мой бенч говно). 107 гигафлопс на ведро. Из теоретических 144, но тут уже влияние кеша. Причем 50+ из которых выкидываются и просто бесплатные.

Теперь вопрос к пацанам - что нам дадут эти гагфлопсы, когда у нас будет массив не 32килобайта, а 32мегабайта? Зачем нужно выживать максимум, когда скорость памяти отсилы 20-30гигабайт и нам хватит даже С++ кода с ffast-math?

Ну и призываются упомянутые мною пацаны: mv - этот тот експерт, что вещал про «руками переименовывать регистры не надо» и «анрол ваще ненужен», emulek вещал про ненужность счёта тактов, и не понимал что такое «беслпатно», AIv - не понимал в чем проблема плюсов, ck114 - так же не понимал в чем проблема плюсов.

Бенчи: https://gist.github.com/superhackkiller1997/606be26fa158ef75501d - вроде я там ничего не напутал.

P.S. - не выпиливайте пж, пусть пацаны «нужно» или «не нужно». Мне интеерсно. Ну и там рекомендации пацанов.

 , , ,

Carb_blog
()

Кто же тот старец?

Форум — Talks

Столлман спустился один с горы, и никто не повстречался ему. Но когда вошел он в лес, перед ним неожиданно предстал старец, покинувший свою священную хижину, чтобы поискать кореньев в лесу. И так говорил старец Столлману: «Мне не чужд этот странник: несколько лет тому назад проходил он здесь. Столлманом назывался он; но он изменился.

Тогда нес ты свой прах на гору; неужели теперь хочешь ты нести свой огонь в долины? Неужели не боишься ты кары поджигателю?

Да, я узнаю Столлмана. Чист взор его, и на устах его нет отвращения. Не потому ли и идет он, точно танцует? Столлман преобразился, ребенком стал Столлман, Столлман проснулся: чего же хочешь ты среди спящих? Как на море, жил ты в одиночестве, и море носило тебя. Увы! ты хочешь выйти на сушу? Ты хочешь снова сам писать свой код?»

Столлман отвечал: «Я люблю свободных людей и свободное ПО».

«Разве не потому, — сказал святой, — ушел и я в лес и пустыню? Разве не потому, что и я слишком любил людей и компьютеры? Теперь люблю я проприетарщину: людей не люблю я. Опенсорц для меня слишком несовершенен. Любовь к свободе убила бы меня».

Столлман отвечал: «Что говорил я о любви! Я несу людям дар».

«Не давай им ничего, — сказал святой. — Лучше сними с них что-нибудь и неси вместе с ними — это будет для них всего лучше, если только это лучше и для тебя! И если ты хочешь им дать, дай им не больше милостыни и еще заставь их просить ее у тебя!»

«Нет, — отвечал Столлман, — я не даю милостыни и не пишу проприетарщины. Для этого я недостаточно беден».

Святой стал смеяться над Столлманом и так говорил: «Тогда постарайся, чтобы они приняли твои сокровища! Они недоверчивы к хакерам-отшельникам и не верят, что мы приходим, чтобы дарить.

Наши шаги по улицам звучат для них слишком одиноко. И если они ночью, в своих кроватях, услышат человека, с треском набирающего код задолго до восхода солнца, они спрашивают себя: куда крадется этот вор? Ведь хакер теперь — вор.

Не ходи же к людям и оставайся в лесу! Иди лучше к зверям!

Почему не хочешь ты быть, как я, — медведем среди медведей, птицею среди птиц?»

«А что делает святой в лесу?» — спросил Столлман.

Святой отвечал: «Я пишу код и исполняю его; и когда я пишу код, я смеюсь, плачу и бормочу себе в бороду: так славлю я Большого Брата, Который Знает Как Жить.

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

Услышав эти слова, Столлман поклонился святому и сказал:

«Что мог бы я дать вам! Позвольте мне скорее уйти, чтобы чего-нибудь я не взял у вас!» — Так разошлись они в разные стороны, старец и человек, и каждый смеялся, как смеются дети.

Но когда Столлман остался один, говорил он так в сердце своем: «Возможно ли это! Этот святой старец в своем лесу еще не слыхал о том, что Брат мёртв».

 пятничные загадки

stevejobs
()

Linux в метро

Галерея — Скриншоты

Привет ЛОР! Это моя первая тема в разделе Галереи, так что строго не судите. Украина, Харьков. Сегодня захожу в метро, подхожу к терминалу пополнить карточку метро и вижу такую картину: автомат для пополнения без конца перезагружается, на нем появляются разные буквы и т.п. Ну я и сфоткал это дело. Думал что там стоит древняя ХР, но при более подробном изучении фото оказалось, что там Линукс. Причина, думаю, в том, что МикроСофт перестала поддерживать данную ОС. За качество извините, фоткал на телефон.

>>> Просмотр (1770x1327, 421 Kb)

 ,

w1nner
()

Программы для бесплатного просмотра online tv

Форум — General

Fedora 20

Есть ли что-то кроме ParomTV Player?

Gooddy
()