Visual Studio .sln/.vcproj generator?

По многочисленным просьбам трудящихся, я поставляю вместе с LibRaw еще и .sln/.vcproj файлы для MS Visual Studio.

Генерирую я их с помощью Qmake и все более-менее работает, но:

  • Иногда (когда Юпитер в Рыбах?) в sln-файле вместо относительных путей оказываются полные, приходится ручками чистить.
  • Проекты содержат AdditionalIncludeDirectories указывающие (абсолютным путем) на mkspecs от моего Qmake.
  • Можно сгенерировать проект для 32-бит, вроде бы можно (хотя не пробовал) для 64 бит, а вот под две платформы сразу - не умеет.
  • Была еще проблема с зависимостями (exe - dll), ибо зависимости ловятся искуственным интеллектом, но вроде я научился добиваться от него счастья.
  • Достали win32:/unix: конструкции в .pro-файлах, блин.
Короче, неаккуратненько, неровно висят.

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

Что я упустил? Какой еще есть варез, который нагенерирует мне sln/vcproj из простых текстовых файлов?

LibRaw 0.14 Alpha

По сложившейся традиции, анонсирую тут новую major версию LibRaw, которая пока существует в альфа-варианте.

Скачать ее можно в обычном месте, почитать формальный Changelog там же, а тут хочется рассказать об изменениях человеческим языком.

До сего момента жизнь в LibRaw была устроена просто: открыл файл (LibRaw::open()), распаковал (LibRaw::unpack()), если своего постпроцессинга нет, то попользовался нашим (LibRaw::dcraw_process()). Если какие-то параметры поменялись, то все сначала, open, unpack и так далее.

Плюс этого подхода в том, что все варится в одном буфере, и распаковывается сразу куда надо и демозаика сразу in-place и все остальное - тоже.

Минус - тоже понятно какой: поменял ББ, даже в интерактивной программе и .... опять надо распаковывать RAW, а скажем в кэноновских CR2 тамошний Хаффман (lossless JPEG) устроен так, что хрен распараллелишь его распаковку. И секунда-две только на 30-мегабайтный CR2 - просто в природе вещей.

Что делаем? Правильно, меняем память на скорость.

Начиная с 0.14 байеровские данные распаковываются в один буфер, а весь постпроцессинг идет в другом. Для байеровских камер это penalty по памяти в 25% (40Mb для 20-мегапиксельной камеры), зато счастье велико есть. Для не-байеровских камер потери больше (вдвое), но там и кадры, как правило, небольшие (sRaw - 3-10 мегапикселов, фовеоны - 4Mpix), а владельцы Sigma SD1 или multi-shot задников могут и пару гигабайт памяти докупить.

Linux 12309 УМВР?

Короче, докладываю:

  • Берем виртуальную машину (4Gb RAM, 200G диск, диск на относительно быстром массиве 6xSAS 7200 RPM, RAID6, типичные скорости I/O туда, если не слишком много потоков - 300-400Mb/sec). Разрешаем юзать все 8 "ядер" CPU (кавычки т.к. ядер 4 + HT)
  • Ставим туда OpenSUSE 11.4, x64, накатываем всех апдейтов. Ядро получается 2.6.37.6-0.5-desktop. Файловая система EXT4:
  • Делаем файло на 10Gb: dd if=/dev/urandom of=file bs=1024k count=10000, потому что с нулями непонятно что там накопирует.
  • И начинаем это файло копировать в соседей:
    for i in 1 2 3 4 5 6 7 8 9
    do
     cp file file-$i &
    done
И иногда оно получается: система встает раком минут эдак на несколько, не реагирует на кнопки и мыши. Более того, окошко в котором был запущен iostat тоже замирает и выяснить какое там IO не получается. Пока оно не замершее - ну нормальный такой IO, 220-300Mb/sec.

Увы, но IO в момент замирания с точки зрения хост-машины забыл посмотреть. Попытаюсь воспроизвести проблему еще раз, но позже.

Holy War (Linux vs FreeBSD)

Вынесу из каментов к прошлому посту:

номер раз:

Это значит что с дисковой/fs в линуксе все настолько загадочно и хреново, что у нас ротейт логов на одной из машин роняет ее регулярно раз в месяц (логи то ротейтятся мгновенно, только апач больше не работает) и помогает только reboot -fn. А на десктопе при копировании больших файлов все задумывается так что анекдот про "сейчас дискетка отформатируется..." как раз про современные Линуксовые ядра. Debian/2.6.разные, ext3/4.

номер два:

Я ловил клина на полминуты только при удалении больших пачек больщих файлов (ie по полгига где-то)

Типа записал жене сериал/дитю мультиков на болванку -- хочешь грохнуть исошку/исходники -- и оно тупит минуты две. В 2.6.39 xfs порефакторили сильно (осталась только его "родовая" болезнь -- файл при создании и до закрытия (или до fsync?) имеет только dnode, и если начать копировать файл (ту же исошку) и в середине дернуть питание -- файл будет пустой)

С другой стороны у меня 4 машины с XFS везде кроме /boot и убитого XFS я не видел еще (хотя питание у меня тут весьма нестабильное)

И, рискуя (стремясь!) спровоцировать Holy War, спрошу я вас: че, типа, так и есть?. И считается нормальным? Ну ладно, xfs вроде починили, но ведь было?

Update: в каментах сообщили правильное название, "баг 12309". Поиск в Яндексе "Linux 12309" приносит истинные лулзы!

Справедливости ради два пункта:

Linux vs FreeBSD

Не могу не попиарить мегатред про Linux vs FreeBSD (зачин: Рамблер-почта переезжает с FreeBSD на Linux, там же в каментах про аналогичный переезд Яндексовского кластера).

От себя хочу заметить что хотя часть аргументов лично мне кажется неубедительной (на мой взгляд "монолитная система" - это преимущество, а репозиторий бинарных пакетов для больших кластеров все едино надо иметь локальным), остальные аргументы верные:

  • виртуализация;
  • средства разработки (и не только поминаемый valgrind, но и VTune, например);
  • вообще поддержка новых технологий: OpenCL, CUDA (это если брать мои интересы), Java опять же.
  • да и вообще ВСЕ: Linux стал mainstream, а FreeBSD - увы.
То есть, натурально, единственный настоящий плюс, который я вижу у FBSD на сегодня - это ZFS (ну и разные мои личные тараканы: от iptables меня тошнит, а от ipf - нет). Ну и монолитность, да, выбрать "Linux-дистрибутив", где все было бы достаточно свежим, но при этом не долбанутым на всю голову - лично мне достаточно трудно, ну так у меня и опыта такого мало, впрочем.

Пора, короче, домашний сервер на Linux переводить. Да и виртуальную рабочую станцию разработчика - тоже.

О фотобарахолке в RSS

Имею повод сообщить, что трансляция барахолки foto.ru в RSS в очередной раз починена. В ленту опять попадают начала текстов сообщений, а не только заголовки, как это было последние несколько недель.

Увы, но при минимальной смене дизайна мне приходится править скрипт импорта.

Более длинное описание сервиса и адреса всех имеющихся фидов тут: О барахолке foto.ru в RSS

О выравнивании

Подниму, пожалуй, из комментариев тему о выравнивании разделов на флэшках.

Имею сказать:

  • Взял в одну руку три флэшки, медленные и быстрые: Transcend 120x (8Gb), Transcend 300x UDMA (16Gb), Sandisk Extreme 60Mb/s UDMA (16Gb). Все три - compact flash, скорость на SD меня пока мало волнует.
  • Во вторую руку взял камеру (5D MkII) и читалку карточек памяти. Читалка несовременная, какая-то левая, USB2.
  • В третью руку ногу взял Paragon Alignment Tool 3.0, а в еще одну руку ногу - Crystal Disk Mark 3.
  • И все это совокупил, благо на эксперимент надо ну минут 10.
Получается

О консистентности

Чтобы на времени компиляции убедиться в том, что у нас MS Visual C++ 2008 SP1+, нужно забабахать вот такое вот:
#if defined(_MSC_VER) && _MSC_VER == 1500 && _MSC_FULL_VER >= 150030729

Ну ладно, ну вот лично я бы две старших цифры в _MSC_VER занял бы под major версию, а две младших - под minor (сервис-паки, то-се), ну ладно, пусть будет два макроса.

Опять-таки, ладно, что MS Visual C++ 2008 это на самом деле Visual C++ 9.0, а _MSC_VER у него 1500. Ну логично же, да?

Но покажите мне пожалуйста табличку в официальной документации (на MSDN, например), где были бы перечислены версии компиляторов и против каждой версии было бы написано значение _MSC_VER и прочих макросов, важных для определения версии компилятора. blogs.msdn и social.msdn не принимаются, я хочу именно что документацию

А если эта табличка там есть (я не нашел), то какой осмысленный запрос надо вфигачить в поиск по MSDN, чтобы искомый документ оказался в первой тройке.

P.S. Нет, я не привередничаю. OpenMP в нужном мне виде правильно работает в VC++ 2010 и в 2008SP1, я и хочу чтобы оно собиралось бы с OpenMP на вышеуказанных версиях, а на более старых - и не думало бы. Аналогичный случай имеется с C++ TR1, который, вроде бы, человеческим тоже стал в 2008SP1.

P.P.S. В blogs.msdn.com, в каментах, сотрудник MS пишет что надо делать вот так:

#if defined(_MSC_VER) && (_MSC_FULL_VER > 150021022 || _MSC_FULL_VER == 150021022 && _MSC_BUILD >= 8)
       cout << "This is VC9 RTM or above." << endl;
#endif

#if defined(_MSC_VER) && (_MSC_FULL_VER > 150030729 || _MSC_FULL_VER == 150030729 && _MSC_BUILD >= 1)
cout << "This is VC9 SP1 or above." << endl;
#endif
У меня нет слов. Еще и _MSC_BUILD (которого нету в VC8/2005 и более старых).

Читая сводки с DRAMExchange

Лет эдак 9-10-11 назад флэш-карточки подешевели до невероятной по тем временам цены: $1 за мегабайт.

И примерно тогда я с удовольствием высчитывал: вот снимаю я в двухнедельной поездке 1000 кадров, в кадре - 4 мегабайта (Canon D30), значит помимо камеры (за $3k) нужно еще взять флэша на $4k.

Понятно, были "фотобанки" (носимые диски на батарейках), флэш дешевел, году к 2006-му оно все стало приемлемо. Вот dpreview все помнит: в начале 2006 года 4-гиговый Sandisk стоил всего $300. Ну то есть 1000 15-мегабайтных кадров (1Ds Mk2) стоило похранить всего-то $1200, а на пленке, по $5 за ролик в среднем, получалось $150. Поэтому народ в фотопоездках каждый вечер анализировал снятое, стирая мусор с флэшек.

Сейчас же приемлемые флэш-карты подешевели до $1.5 за гигабайт, а приличные - до $3 (нет, понятно, можно найти позолоченную со стразами). Оптом же $1/гигабайт (ссылки не даю, на DRAMExchange для просмотра этой таблички нужна регистрация).

А гигабайт - это, для ровного счета, 36 20-мегапиксельных кадров.

Таким образом, если экономически приемлемо было снимать на слайд по $5-8 за ролик, то можно и флэшки использовать ровно один раз, это будет втрое дешевле съемки на слайд (и раза в полтора дешевле негатива), не считая проявки.

А, да, отснятые CF-ки удобно хранить в сливерах для слайдов в рамках.

Об автоматической векторизации

Провел на поминавшемся вчера ISPC еще один тест, на применимость ровно в том месте, куда он лучше всего приспособлен.

Есть такое ужасное место в обработке изображений (уже поминавшееся в этом блоге): преобразование из линейной гаммы в sRGB-гамму или в Lab. Там в формуле сначала линейный участок, а потом степенной. Вот как это выглядит, если делать в лоб для плавающей точки:

void linear2srgb(float *in, float *out)
{
   for(int i = 0; i< DATA_SIZE; i++)
        out[i] = ((in[i]<=0.0031308f)? 12.92f*in[i] : (1+0.055f)*powf(in[i],1/2.4f)-0.055f);
}

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

  • ветвление на каждое входное данное;
  • возведение в степень, которое тоже очень медленное: на SSE/AVX такой функции нет, на FP87 есть, но безобразно медленная.
К примеру, при обработке плавающих данных LCMS (преобразование в Lab, преобразование по матричному профилю в sRGB) процентов 90 времени уходит именно на вышепоказанную операцию (правда в LCMS это место еще сделано потрясающе неудачно с точки зрения производительности).

Как я уже писал, правильное решение заключается в замене вышепоказанной функции чем-то приличным, скажем для кубических сплайнов с таблицей в 4к строк максимальная ошибка по всему диапазону не превышает 10-6, что для всех применений достаточно, при скорости порядка 1.2-1.5Gb/sec на одно процессорное ядро. Но одна строчка кода превращается в несколько десятков, таблицу коэффициентов сплайнов надо еще построить, что мучительно.

Посмотрим, что можно сделать с помощью ISPC и можно ли вообще что-то.

Об 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 раз.

Pages

Subscribe to blog.lexa.ru: все статьи