Thursday, May 26, 2011

Удается ли "одновременно делать деньги и творить добро"

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

Уважаемый С.Пачиков (помните основателя "ПараГрафа"?) пишет это в комментариях к интервью "В России нет государства", интервью с Ульямом Браудером, открывшим Европарламенту детали дела Магнитского. Открывающим и нам. Страшное дело.

Sunday, May 08, 2011

"Совершенная строгость"

Получил сегодня после обеда книгу и, не отрываясь, прочитал ее - “Совершенная строгость (Perfect Rigor). Григорий Перельман: гений и задача тысячелетия” Маши (почему тогда не Гриша) Гессен. Исходно относился к книге скептически: как можно писать о человеке, ни разу не поговорив с ним. Но книга увлекла. Увлек образ мальчика, ставшего математиком. Конечно, некоторые фрагменты книги пришлось проигнорировать, не в смысле чтения, а в эмоциональном, в смысле принятия написанного. Скажу о них позже. Но книгу надо читать.
Невозможно определить, насколько близки реальный Перельман и впечатления о нем автора книги, друзей, одноклассников и коллег Перельмана, решившихся отвечать на вопрос, какой он. Возможно, что безнадежно далеки, и он реальный, гораздо выше тех представлений о нем, как математике и человеке, которые можно получить из книги. Занимаясь пространствами Александрова, Перельман, видимо, как и его учитель, “открыл в математике новые миры и сейчас пребывает там в одиночестве”. Кажутся убедительными выводимые объяснения Маши Гессен (хотя и не приведены явно, как причины), почему Перельман отказался от наград и “ушел”. Вообще, становятся ясными два пере-открытия: 1. для того, чтобы совершить значительное, надо паталогически игнорировать все, что не служит цели (в предположении, что одарен и служишь цели); 2. не рассчитывать на деликатность сообщества, если достиг. Первое словами автора: “Перельману в математике удавалось то, что он пытался делать в жизни: охватить все возможности, существующие в природе, и отбросить все, что выходит за рамки естественного - будь то голоса кастратов, автомобили, антисемиты или еще какие неудобные сингулярности”. Иллюстрацией ко второму может стать такой факт: “Третьего июня Яу созвал в своем математическом институте в Пекине пресс-конференцию и объявил: “Вклад Гамильтона в доказательство составляет около 50%, россиянина Перельмана - около 25%, китайцев Яу, Чжу, Цао и других - около 30%””.
То, что я “игнорировал” в тексте: рассказы о завязанной шапке; брошенной скрипке; о зарплате аспирантов, которой хватало на 3 буханки хлеба; математике, основавшем правозащитное движение в СССР; секс-ориентации Колмогорова. Кроме того, Маша Гессен, видимо, попыталась поставить диагноз, написав главу о синдроме Аспергера. Неудобство, также, вызвали примечания к текстам. Сами примечания - доказательны (даны источники) и полезны, но ссылок на них в тексте нет.

Автор, Маша Гессен, является заместителем главного редактора проекта “Сноб

Wednesday, May 04, 2011

Блочное умножение матриц

Продолжение.
Этот пост - продолжение предыдущего, где обсуждалась производительность кода, генерируемого LLVM, по сравнению с GCC и ICL на примере умножения матриц. Тестировались реализации без блокирования. Здесь представлены результаты измерения производительности блокирующего алгоритма и пример автоматической генерации кода.
Поблочное умножение.
Алгоритм реализован для произвольных размеров матриц и блока. Производительность сравнивается с реализаций на asm как самой быстрой.
Ничего удивительного на графике не найти. Как бы ни был быстр asm код, обработка больших матриц и доступ к данным за пределами кэша ведет к замедлению. Видно падение производительности для объемов данных, превышающих 4 MB. Обработка по блокам, в основном, имеет дело с данными, лежащими в кэше, поэтому быстрее и, как видим, значительно. Умножение блока выполняется тем же самым asm кодом, с которым сравниваем. Скачки для блочной реализации объясняются разными размерами блока. При произвольности параметров есть условия максимальной производительности:
  • размеры матриц кратны размеру блока,
  • размер блока кратен 8-ми элементам (два SSE2),
  • указатели выравнены на 16 байтов.
Использовал размер блока до 256х256. Каждый раз максимальная производительность достигалась при наибольшем размере блока. Небольшой размер блока дает гибкость в обработке (бо'льшая часть матриц может быть накрыта блоками), но добавляет больше непроизводительных операций (копирование данных в/из блока)
Код можно генерировать
Может оказаться интересным автоматическая генерация кода, возможная, например, при использовании metaocaml. Сгенерировать код умножения матриц с разверткой циклов обнуления массива результата и внутреннего цикла умножения элементов матриц можно с помощью такого кода
Использованы 2 функции развертки: одна разворачивает весь цикл, другая разворачивает цикл до 256 с фактором. Развертка, как видим, выполняется на 8. Размер блока фиксирован - 256х256. Мета-средства, а именно, многостадийное программирование multistage programming , нужны здесь для генерации тела операции, которая размножается. В коде таких две: присвоение нулю и умножение элементов. С помощью офшоринг-механизма ".!{Trx.run_gcc}" генерируется следующий С-код
void mmm_256_u(float*a_4,float*b_5,float*c_6)
{
 int i_7 ;
 for(i_7 = 0; i_7 <= 255; i_7++)
 {
   int i256_8 ;
   int ii_13 ;
   int k_9 ;
   i256_8 = i_7 * 256;
   for(ii_13 = 0; ii_13 <= 32 - 1; ii_13++)
   {
     c_6[i256_8 + (ii_13 * 8 + 0)] = 0.;
     c_6[i256_8 + (ii_13 * 8 + 1)] = 0.;
     c_6[i256_8 + (ii_13 * 8 + 2)] = 0.;
     c_6[i256_8 + (ii_13 * 8 + 3)] = 0.;
     c_6[i256_8 + (ii_13 * 8 + 4)] = 0.;
     c_6[i256_8 + (ii_13 * 8 + 5)] = 0.;
     c_6[i256_8 + (ii_13 * 8 + 6)] = 0.;
     c_6[i256_8 + (ii_13 * 8 + 7)] = 0.;
   } ;
   for(k_9 = 0; k_9 <= 255; k_9++)
   {
     int k256_10 ;
     float aa_11 ;
     int ii_12 ;
     k256_10 = k_9 * 256;
     aa_11 = a_4[i256_8 + k_9];
     for(ii_12 = 0; ii_12 <= 32 - 1; ii_12++)
     {
c_6[i256_8 + (ii_12 * 8 + 0)] = c_6[i256_8 + (ii_12 * 8 + 0)] + aa_11 * b_5[k256_10 + (ii_12 * 8 + 0)];
c_6[i256_8 + (ii_12 * 8 + 1)] = c_6[i256_8 + (ii_12 * 8 + 1)] + aa_11 * b_5[k256_10 + (ii_12 * 8 + 1)];
c_6[i256_8 + (ii_12 * 8 + 2)] = c_6[i256_8 + (ii_12 * 8 + 2)] + aa_11 * b_5[k256_10 + (ii_12 * 8 + 2)];
c_6[i256_8 + (ii_12 * 8 + 3)] = c_6[i256_8 + (ii_12 * 8 + 3)] + aa_11 * b_5[k256_10 + (ii_12 * 8 + 3)];
c_6[i256_8 + (ii_12 * 8 + 4)] = c_6[i256_8 + (ii_12 * 8 + 4)] + aa_11 * b_5[k256_10 + (ii_12 * 8 + 4)];
c_6[i256_8 + (ii_12 * 8 + 5)] = c_6[i256_8 + (ii_12 * 8 + 5)] + aa_11 * b_5[k256_10 + (ii_12 * 8 + 5)];
c_6[i256_8 + (ii_12 * 8 + 6)] = c_6[i256_8 + (ii_12 * 8 + 6)] + aa_11 * b_5[k256_10 + (ii_12 * 8 + 6)];
c_6[i256_8 + (ii_12 * 8 + 7)] = c_6[i256_8 + (ii_12 * 8 + 7)] + aa_11 * b_5[k256_10 + (ii_12 * 8 + 7)];
     } ;
   } ;
 } ;
}

Пришлось отредактировать только тип данных, заменил double на float - ocaml знает только тип данных с плавающей запятой double. Производительность кода с разверткой плохая. Как мы уже упоминали, ручная развертка мешает Intel компилятору векторизовать код. Следовательно, средства мета-программирования, использованные здесь для развертки, оказались неприменимы.
Высокой производительности достигает код без развертки, генерируемый из такого ocaml кода
ICL успешно векторизует оба цикла и обеспечивает производительность близкую к производительности asm кода - чуть хуже, смотри красный кружок на первом рисунке. Итак,
для матриц размером 2072x2072 и блоков размером 256x256
  • unrolled: 1161 MFlops,
  • vectorized by ICL: 2339 MFlops.
Многостадийное программирование особенно эффективно в тех случаях, когда на этапе компиляции известна дополнительная информация о данных. Например, есть умножения на 1.0 или 0.0, или вычисляются значения тригонометрических функций для pi/2, pi/4. Примером такой задачи является FFT, решение ее подробно рассмотрено в работе "A Methodology for Generating Verified Combinatorial Circuits" авторами O.Kiselyov, K.N.Swadi и W.Taha - восхитительный образец использования мета-программирования.