Программирование

Об Intel ISPC

Интел выкатил в опенсорс такую вот игрушку: Intel SPMD Program Compiler.

Это очередная попытка придумать параллельный язык C: пишете некую функцию, к примеру, обрабатывающую элемент данных, варез сам строит SIMD-представление (SSE, AVX), которое обрабатывает 4(8) элементов за раз. Ну как-то так:

void vector_sum(uniform float in[], uniform int count, reference uniform float out[]) {
    float sum = 0.0;
    for (uniform int i = 0; i < count; i += programCount) {
        int index = i + programIndex;
        sum+= in[index];
    }
    out[programIndex] = sum;
}
И оно у вас пойдет фигачить шириной programCount, ну там дальше надо будет элементы out просуммировать уже снаружи.

Об Intel OpenCL

Щупаю тут за вымя Intel OpenCL (для CPU) и эта игрушка мне все больше нравится.

Помимо оффлайн-компилятора (который выдает ассемблер или LLVM-код) эту хреновину можно профайлить при помощи VTune (нужно пару переменных окружения поставить, см. доку).

Беру я, значит, прямо тамошний пример MedianFilter и начинаю профайлить. Он содержит "CPU"-реализацию (в том смысле, что компилятор C++ ее превратит в обычный код) и OpenCL-вариант (который будет скомпилирован на лету). Обе реализации имеют настолько одинаковый C/C++ код внутри, насколько это вообще возможно (OpenCL-ядро - это обработка одной строки изображения, а CPU-код имеет еще цикл по всем строкам). Код, собственно, простой как пробка: берем пикселы из окрестности +-1, слегка сортируем (unrolled), вот и медиана.

И вот что я вижу:

  • CPU-вариант при компиляции Visual C++ 2008: 389 msec на исполнение. Это без processor-specific оптимизаций и без распараллеливания.
  • OpenCL-вариант: 15 msec.
В 26 раз быстрее, однако.

Ну ладно, VC++2008 - не самый новый, да и процессора моего не знает. Переключаю компилятор на Intel C++ 12-й версии (который Composer XE), включаю оптимизацию для AVX, уже лучше: 151 msec. Но тоже в 10 раз.

Не все йогурты одинаково полезны

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

Более того, реализаций для CPU уже две на виндах: AMD-шная входит в состав ATI Catalyst (драйверов для видеокарты) и даже при отсутствии подходящей видеокарты эта часть драйверов поставится. Кроме того, Intel-овский OpenCL на днях перешел из стадии альфа в бету. На Linux, кстати, есть еще IBM-овский OpenCL для CPU, все руки не доходят его ощупать.

Берем AMD-шный пример BitonicSort из APP SDK 2.4 (это AMD-шный SDK для GPGPU) и запускаем, без перекомпиляции, прямо на всех имеющихся в машине девайсах и реализациях. Сортируем 16 млн. элементов. В порядке падения быстродействия:

  1. Intel OpenCL (процессор i7-2600k @4.5Ghz): 10.6 сек.
  2. NVidia OpenCL (GTX480, драйвер 270.61): 16.4 сек.
  3. AMD OpenCL (Radeon 5870, драйвер 11.4): 29.3 cек.
  4. AMD OpenCL на CPU (тот же самый): 415 сек.
Я подозреваю, что AMD-шный OpenCL в случае CPU просто процессор не опознал и сгенерировал код для 8086 или что-то вроде этого. Для CPU AMD Kernel Analyzer показывает нам невекторизованый код, т.е. процессор не опознался и что под него генерировать AMD не знает. На предыдущем процессоре (i7-920) такой разницы с интеловским OpenCL (тогда он был в первой альфе) не было. При этом, при исполнении на AMD-OpenCL процессор загружен где-то на четверть, а "под интелом" - на 100%

Прикол тут в другом: по формальному быстродействию горшки ранжируются в обратном порядке: у AMD бешеные 2 терафлопса на float (по пресс-релизу AMD: 2.7 TFLOP/s), у NVidia - раза в два поменьше (в районе 1.35 TFLOP/s если формально считать), у CPU же, даже если AVX посчитать как 16 операций на такт (две AVX-операции на такт) получается 16 x 4 ядра x 4.5 гигагерца = 288 GFLOP/s.

Понятно, что сортировка - дело такое, для потоков плохо предназначенное.

Чтобы два раза не вставать: большинство AMD-шных примеров на GTX480 работает быстрее (и лишь некоторые - незначительно медленнее), чем на HD5870. Несмотря на формальные попугаи, говорящие об обратном. Обратного, чтобы OpenCL-примеры NVidia работали бы быстрее на AMD, - не наблюдается.

Update: Помучал тот же пример на машине с i7-920 и GTX280. AMD OpenCL/CPU никуда не годится и там, увы. Может быть надо kernel как-то иначе писать. Что же касается реализаций Intel (CPU) и NVidia (GPU), то на этой паре железок и BitonicSort они работают практически одинаково по скорости.

О взаимном знании двух рук

Надо сказать, что сочетание Sandy Bridge и интеловских средств профайлинга производит тягостное впечатление.

На i7 (предыдущего поколения) был у меня VTune Amplifier XE из состава Intel C++ Composer XE (12-я версия компилятора, а версию VTune я не считал). И все работало, никаких проблем.

После замены процессора VTune сказала мне, что hardware sampling на этой архитектуре она не умеет. Ну ладно, компилятор вышел в конце 2010-го, тогда Sandy Bridge в продаже не было (у интела, впрочем, были, как мне кажется).

Ставим C++ Composer XE update 1 (где-то февральский, если я не путаю). При установке он предупреждает, что тоже не умеет hardware sampling на этой архитектуре. Ну, странно да. Одновременно отваливается и User Mode Sampling, да.

Но есть еще VTune Amplifier XE update 2, совсем свежий. Ставим его. Аппаратный самплинг появляется, но User Mode так и не работает. И это известная проблема, советуют you can try to re-install the product. Running it on a different machine should help also. Тьфу. Как-то я был лучшего мнения об интеловских разработках.

Конечно, с lightweight hotspots (без анализа стека) можно как-то жить, но довольно неудобно. MS-овский профайлер работает настолько медленно, что это ужоснах.

Да, я try reinstalling, не помогло. Different machine у меня в данный момент нет.

Зыбкий мост

Долго крепился, но против желания попрограммировать на AVX устоять невозможно.

Приколы Sandy Bridge/P67:

  • У Асуса на сайте написано "в связи с ограничениями чипсета P67, память 1866 работает как 1600". И вправду. Ставишь 1866 (память поддерживает по спекам, на X58 работала на 1800) - все начинает валится с грохотом, Win7 ни разу не загрузились, но каждый раз с разной ошибкой. На 1600 - все отлично.
  • CoreTemp 0.99.5 показывает удвоенную температуру (в цельсиях). Гы.
  • Я подозревал, что скорость линейного чтения/записи памяти пострадает. На X58 было три канала, тут - два, память одна и та же. Жизнь оказалась веселее:
    • С точки зрения SiSoft Sandra Lite, у меня было 25Gb/sec memory bandwidth на i7-920 (3 канала), а стало 20Gb/sec на i7-2600K (2 канала). И я даже с этим не спорю.
    • Но вот AIDA64 (бывш. Everest) считает, что было 16/14/19 (GB/sec,read/write/copy), а стало 19/19/21
    И логика велит мне согласиться с Сандрой (каналов меньше, память та же), а сердце говорит, что в моих личных тестах я получал цифири, куда более близкие к эвересту.
Пойду, до пяти гигагерц ея разгоню.....

Суббота для человека или человек для субботы?

Со всевозрастающим изумлением читаю дискуссии про memcpy, glibc, Линуса, Adobe и Дреппера:

(русскоязычные - они свежие, на LWN все уже отшумело три месяца назад).

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

А значит - это прекрасный вопрос для собеседования, причем важен не столько ответ, сколько его объяснение, а за вторую сторону можно легко потроллить. Я бы сказал, что от PM и выше - просто обязательный вопрос, а для кодеров - мировоззренческий. И не надо собирать в одной команде (компании, стране, вселенной) людей, отвечающих на этот вопрос по-разному.

Для тех кто в танке, суть проблемы (при взгляде с одной из сторон):

О платформах и технологиях

Вот берем два Друпальских модуля внешней авторизации:

  • Facebook Connect - позволяет одним кликом создать аккаунт на друпальском сайте, все мгновенно.
  • OpenID - аккаунт создать позволяет, но не верифицированный, уйдет E-mail, на полученный линк надо будет кликнуть (да и то, эта функциональность не так давно появилась, раньше можно было только существующий аккаунт привязать к OpenID-URL).
И сначала я на поведение OpenID ругался (про себя, да и вслух), а потом осознал сермягу:
  • В случае Facebook (ЖЖ, Твиттера, Вконтакте, MailRU....) я доверяю (или не доверяю) конкретному сервису (платформе). А они, в свою очередь, пытаются (своими немаленькими ресурсами) отличить людей от роботов и все такое. Список доверенных - невелик, а если вдруг чего, то и отозвать доверие недолго.
  • В случае протокола (технологии) - доверие делегируется неизвестно кому. Какому-то Васе или Пете, который асилел OpenID-сервер поднять. Но я точно знаю, что средний спамер (что по каментам, что по почте) технологически гораздо продвинутее, чем просто средний Вася. Более того, спамеры на порядки активнее "просто пользователей".
Получается, доверять технологии - нельзя. Платформе, за которой стоят конкретные люди и силы, заинтересованные в хорошей работе платформы - можно. Платформа может быть распределенной, конечно, но не изолированными островками неизвестного количества.

Мораль: OpenID труп.

День друпала

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

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

О плавающей точке

Что напечатает:
  unsigned short v=59259;
  float a=0.0f;
  double b=0.0;
  for(int i=0;i<33*33;i++)
  {
        a+=v;
        b+=v;
  }
  printf("%g\n",(a-b)/(33*33));

Вроде и значения все вполне небольшие, и число итераций сложения вполне человеческое, однако ж.

P.S. При особом везении тут можно и третий знак разницы получить, а не шестой....

О стандартных форматах

Программировал тут вывод в формат CGATS (это в котором всякие цветовые замеры выводятся, пример ниже), по которому я тут уже немного проехался.

Заодно посмотрел много (десятки) примеров таких файликов, чтобы слова списать. Ну и исходники Argyll на предмет "как это читают".

Если кто-то имеет иллюзию, что это такой вот стандартный формат, который все понимают одинаково и все такое прочее, того жизнь еще не била. Даже форматы данных Пенсионного Фонда РФ - луч света в темном царстве в сравнении с CGATS.

Вот, например, загадка:

  • Допустим, у меня в файле есть и LAB и RGB значения.
  • Допустим, там же есть и стандартные отклонения замеров. Начинаем называть колонки: STDEV_L, STDEV_A, STDEV_B, STDEV_R, STDEV_G, STDEV_что?
  • С XYZ/CMYK, кстати, аналогично.

О Qt и рисовании прямоугольничков

Мой опыт с Qt достаточно своеобразен: как только я начинал лобзиком выпиливать что-то свое руками, внезапно обнаруживалось, что все украдено до нас и есть уже готовое или почти готовое решение. Из последних открытий в этом месте: QGraphicsItemGroup, подошедший мне на 98% после того, как я изготовил свое частное решение (которое, конечно, выкинул после этого).

Но вот столкнулся с задачкой, которая, вроде бы, не решена:

Дано: картинка (разноцветная), на которой рисуются прямоугольнички (selections). Чтобы они были видны на любом фоне, нужно делать XOR в каком-то виде. Или что-то подобное.

В-принципе, QPainter это все умеет, у него есть CompositionMode, где все подобные преобразования можно задать. Но:

Друпалеру на заметку

Если у вас по каким-то причинам есть запись в таблице node, но нет ни одной записи с таким nid в node_revisions, то у вас ВНЕЗАПНО начнут портиться права доступа. Причем rebuild permissions будут помогать ненадолго, до попытки создания очередной node.

Детектируется проблема элементарно:

 select nid from node n where not exists (select nid from node_revisions r where r.nid=n.nid);
Лечится - таким же delete.

Но я сегодня чуть не фалломорфировал, разбираясь.

Почему создание записи с revision не обернуто в транзакцию - мне удивительно, но подозреваю что это привет от MySQL.

О комментариях в программах

Свежий GPU Computing Toolkit 4.0 Release Candidate. Кусок кода примера (OpenCL RadixSort):

//All three kernels run 512 threads per workgroup
//Must be a power of two
#define WORKGROUP_SIZE 256

P.S. Я, по возможности, стараюсь в своих программах комментариев не писать. По вышепоказанной причине. Опять же, FreeBSD kernel is very well documented.

...может задолбать небольшого слона....

Все-таки я продолжаю считать, что кавардак с многочисленными несовместимыми рантаймами не украшает Microsoft Windows вообще и MSVC в частности.

Ситуация:

  • Свежий Qt 4.7.2, собранный (в Нокии) MSVC 2008
  • Мой варез, который я собираю лично MSVC 2010
До вчерашнего дня у меня был Qt 4.7.1 собранный самостоятельно (тем же MSVC 2010) и все было отлично. Заменяю Qt на DLL, собранные в Нокии, qmake (перегенерация мейкфайлов т.е. ключи компиляции гарантированно правильные), перекомпилирую, и что имею:
  • В целом варез работает.
  • В частностях валится с грохотом, где-то в недрах (отладчик, впрочем, говорит что Heap Corrupted т.е. эти недра - опять аллокаторы).

QT/MVC

А зря меня пугали Qt-шным QModelIndex и вообще тамошним MVC.

Оно там чумовое, очень удобное, логичное и вообще мне нравится.

То есть, конечно, вся иерархия немножко перетяжеленная, но примеров из Advanced Qt Programming вполне достаточно, даже соответствующие главы из книжки можно целиком не читать.

О Qt

  1. Qt делали негуманоиды (как и многое другое).
  2. Но у этих конкретных негуманоидов под чешуей проглядывает что-то человеческое...

LibRaw 0.13-Beta1

Отметим завершение каникул анонсом LibRaw 0.13-Beta1.

Сегодня на экране:

  • Ускорение распаковки хаффмана за счет более правильной буферизации (а для файлов .CR2 - еще и за счет правильного пред-расчета смещений). В результате LibRaw::unpack() работает раза в полтора быстрее для .CR2 и на 20-30% быстрее для других подобных форматов (NEF, packed DNG).
  • Масса новых плюшек в demosaic packs (похоже, пора их переименовывать в feature packs):
    • Шумопонижение разных видов (подавление banding, подавление импульсного шума, выравнивание зеленых каналов).
    • Новый, более правильный, алгоритм автоподавления хроматических аберраций.
    • Правильная экспокоррекция с возможностью сохранять детали в светах (аналог compressed exposure в RPP).
    • Ускорение медианных фильтров при помощи OpenMP
  • Ну и, естественно, все фиксы из ветки 0.12
Все это благолепие - скоро в digiKam (собственно, кроме экспокоррекции - оно уже там).

OpenMP: Intel vs Visual Studio

Непонятки с производительностью OpenMP в случае VisualStudio (см. еще обсуждение в каментах) заставило разобраться.

Выяснилось, что две переменные, которые read-only и вообще объявлены как const - считаются разделяемыми. Как следствие - локи при обращении и прочие удовольствия.

После устранения этого недоразумения (#pragma omp ... private(...)) и замены _mm_store_ps() на _mm_stream_ps(), чтобы в обеих компиляторах выходной массив писался через movntps, все встало на свои места: С-шный код с powf() остается сильно быстрее у Интела т.к. он векторизует powf в _svml_powf4, а SSE-код работает с практически одинаковой скоростью.

Его пример другим наука:

#pragma omp parallel for default(none)
и явное прописывание shared/private/whatever для всех переменных.

О степенной функции, OpenMP и прочих граблях

Есть вот такое вот известное выражение, переложеное из википедии:

#define To_sRGB(q) (((q)<=0.0031308f)? 12.92f*(q) : (1+0.055f)*powf(q,1/2.4f)-0.055f)
В том смысле, что у sRGB внизу - линейный участок, а дальше степенная функция.

Если его напрямую запрограммировать (вот прямо с powf()), то в зависимости от компилятора получается от 7 Mpix/sec (Visual C++ 2010, один поток) до 100Mpix/sec (Intel Parallel Studio XE, включен OpenMP). Пиксель - это 3 компонента по 4 байта (float), то бишь гигабайт с небольшим в секунду - это максимум.

Как-то медленно.

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

Pages

Subscribe to Программирование