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

Qt licensing - 2

Нам пишуть:

Dear Qt User:
Nokia is pleased to announce that with the release of Qt 4.5 you will be able to use Qt under the Lesser General Public License (LGPL) version 2.1 terms. When released in March 2009, Qt will be made available under three licensing options: Commercial, LGPL and GPL. Prior versions of Qt are not impacted by this announcement.

Спасибо компании Nokia за поэкономленные 5 килобаксофф (скидки для Small business/Startup они отменили осенью)

Ручная работа!

5d2-mask.png

Если рассматривать черную рамку у 5D Mark II, взяв кадры с разных камер, то становится очевидно, что матрицы делаются вручную (китайские крестьяне в своих фанзах?). Вот, собственно, пример: два кадра (сложены слоями в фотошопе со смещением), оба ISO 100, камеры разные. У одного по верхнему краю просто насечки от шестеренки, а у другого - еще и темная полоса.

Не корысти ради...

... а только с целью тестирования LibRaw и улучшения ея качества.

Имеется острая нужда в RAW-файлах следующих форматов:

  • Sony DSC-F828 Огромное спасибо за помощь!
  • Задники Imacon Ixpress - нужны RAW-файлы в родном формате;
  • Задники PhaseOne - нужны RAW в нежатом формате;
  • Задники Sinar - нужны RAW-файлы, снятые в режиме 4-shot

Если у вас есть такое оборудование, либо же просто файлы в данном формате (что изображено - неважно, мне сами данные нужны) - свяжитесь со мной пожалуйста, придумаем способ как передать.

(Р)эволюция продолжается: LibRaw 0.7.0 Alpha-0

Вышла LibRaw 0.7.0-Alpha0.

Это довольно важный релиз, открывающий массу новых (но пока - потенциальных) возможностей для разработчиков, над некоторыми вещами я в фоновом режиме думал с начала осени и тороплюсь поделиться:

As RAW as possible

kaf50100.png Говоря о RAW-данных ("необработанные", "данные прямо с матрицы") большинство фотографов (да и не только фотографов) полагают, что сенсор - это очень простая штука: массив светочувствительных элементов, цветные фильтры, сбоку прикручен АЦП (или несколько). Появляется в рекламных буклетах производителей фраза "мы уменьшили зазор между микролинзами" - вспоминают еще и про микролинзы. Документации то разумной почти нет. Про острую нужду в кривых спектральной чувствительности мы уже писали в статье для Компьютерры, но есть острая нужда не только в этих данных.

Вот, например, "черная рамка" или маскированные пикселы. Они считываются с матрицы, но в финальное изображение - не попадают. Значения считанных оттуда пикселов - это источник данных для выставления уровня черного. Если читать исходные тексты dcraw, то видно, что для большого числа камер Dave Coffin (а за ним - и многие последователи) банально вычисляет среднее по некоему участку черной рамки (или же в последних версиях для некоторых камер делает чуть-чуть сложнее, считая отдельное среднее для четных и нечетных столбцов), затем это среднее вычитается из значений, считанных с активных пикселов и все.

Впрочем, некоторые производители завесу немножко приоткрывают. Вот, скажем, Kodak. В Кодаковских datasheets на сенсоры написано много всего интересного. И если почитать, например, документацию на KAF-50100 (картинка справа взята из нее), то становится понятно, что структура неактивных пикселов - сложная, тут и референс для выставления уровня черного и что-то тестовое и какие-то буферные пикселы.

LibRaw 0.6.4

C Новым Годом, товарищи читатели!

Использующим LibRaw мой новогодний подарок: LibRaw 0.6.4.

Исправлена ошибка с утечкой файловых дескрипторов и памяти под буферы при извлечении thumbnails. Проявиться она могла только при некорректном использовании библиотеки, однако народ наступил на...

Qt commercial licensing Qs

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

Вот читаю я веб на предмет не-опенсорсного лицензирования Qt, сильно удивляюсь и имею вопросы. Саму политику компании Trolltech Nokia обсуждать не хочу, поэтому вопросы очень конкретные (тамошним sales я тоже написал, но ответа 30-го декабря не ожидаю).

  • На вебе не написано, но верно ли я понимаю, что покупка лицензии - одноразовый процесс, каждый год платить несколько штук за девелопера не надо (предположим, что техсаппорт мне не нужен).
  • Какова политика апгрейдов, купив сейчас 4.4 получу ли я право на 4.5 или 5.0?
  • The license is sold on a per-developer basis and assigned to an individual. Когда individual увольняется - уносит ли он лицензию с собой? Или она просто пропадает? (про 6-месячный transfer right я тоже видел, допустим 6 месяцев прошло).
  • Ну и более частный вопрос - если я найму такого индивидуала на почасовую оплату, чтобы он с нужной частотой билдил мне релизы из объектных файлов, которые я ему дам - как это будет выглядеть с позиций лицензионного соглашения TrollNokia?
  • Update: еще вопрос. Купив лицензию только на Венды, можно ли потом обновиться на три платформе по цене разницы в стоимости лицензий? И аналогичный вопрос про Desktop Lite - мне Networking и SQL пока даром не упали, но если понадобится - получится ли обновиться за дельту в цене?

Не то, чтобы разовые $5300 (пруфлинк) на три платформы - безумно много, но пока у меня в этом месте не планируется никакого бизнеса, только всякое собственное развлечение.

Drupal Comment Notify + PostgreSQL = ....

Продолжаю воспитание модулей Drupal. В этот раз под горячую руку попал Comment Notify, захотелось разобраться, почему автор Друпала выбрал именно его.

Как оно регулярно бывает с Друпалом, этот модуль с PostgreSQL тоже не работает. И почему я не удивлен.....

Вместе с тем, количество требуемых изменений очень невелико и патч вполне компактный. Проблемы обычные: ifnull, concat, "UPDATE table LEFT JOIN table2".

comment-notify-1.1-pgsql.diff.gz

Продолжаю воспитание модулей Drupal. В этот раз под горячую руку попал Comment Notify, захотелось разобраться, почему автор Друпала выбрал именно его.

Как оно регулярно бывает с Друпалом, этот модуль с PostgreSQL тоже не работает. И почему я не удивлен.....

Вместе с тем, количество требуемых изменений очень невелико и патч вполне компактный. Проблемы обычные: ifnull, concat, "UPDATE table LEFT JOIN table2".

comment-notify-1.1-pgsql.diff.gz

Drupal Comment Subscribe 6.x-1.2 и PostgreSQL

Я тут в соседнем микроблоге уже нажаловался на моральных индусов. А в этом блоге - конструктив.

comment_subscribe-12-pgsql.diff.gz

Накладывается поверх чистой установки (или апгрейда) модуля Comment Subscribe версии 6.x-1.2. Исправляются несовместимости с PostgreSQL плюс немножко еще:

  • Утерянные автором мои патчи к предыдущей версии - восстановлены (автор взял не все.
  • Правится (внесенная мной же, потом поправленная мной, но не автором модуля) бага с отсылкой многих одинаковых сообщений одному получателю.
  • Подписка автора ноды на все комментарии к ней может редактироваться (в авторской версии - только ставится в момент создания).
  • Таблица с подписками на все комментарии заполняется, даже если на сайте нет ни одного комментария.

Патч сейчас засабмичу автору, посмотрим на результат второй итерации....

NVidia GTX280: бенчмарки с плавающей точкой

gtx280.jpg Каждые полгода мы с друзьями я бенчмаркаю вычисления на видеокартах. В этот раз изучалась NVidia GTX280.

SGEMM/DGEMM на видеокарте и CPU, серия 7: NVidia GTX280
В чипе NVidia G200 появились операции с двойной точностью. Их производительность не феноменальна, но даже с учетом ввода-вывода данных в карту GTX280 обгоняет 4-ядерный 3-гигагерцовый Penryn. Если же рассматривать только скорость вычислений (что актуально, если задача позволяет спрятать затраты на ввод-вывод), то на двойной точности видеокарта быстрее CPU в 1.8 раза.
На одинарной точности разрыв видеокарты и CPU вырос: GTX280 обгоняет Core2Quad впятеро.

Понятно, что Core i7 разницу несколько сократит, но по тем бенчмаркам с плавающей точкой, что я видел (а видел я пока только Linpack, причем не факт что в оптимальном для i7 виде), рост в производительности i7 - процентов 20.

Всякие соображения про масштабируемость решения - в самой статье.

gtx280.jpg Каждые полгода мы с друзьями я бенчмаркаю вычисления на видеокартах. В этот раз изучалась NVidia GTX280.

SGEMM/DGEMM на видеокарте и CPU, серия 7: NVidia GTX280
В чипе NVidia G200 появились операции с двойной точностью. Их производительность не феноменальна, но даже с учетом ввода-вывода данных в карту GTX280 обгоняет 4-ядерный 3-гигагерцовый Penryn. Если же рассматривать только скорость вычислений (что актуально, если задача позволяет спрятать затраты на ввод-вывод), то на двойной точности видеокарта быстрее CPU в 1.8 раза.
На одинарной точности разрыв видеокарты и CPU вырос: GTX280 обгоняет Core2Quad впятеро.

Понятно, что Core i7 разницу несколько сократит, но по тем бенчмаркам с плавающей точкой, что я видел (а видел я пока только Linpack, причем не факт что в оптимальном для i7 виде), рост в производительности i7 - процентов 20.

Всякие соображения про масштабируемость решения - в самой статье.

Хозяйке на заметку: перенос в Drupal комментариев под другую ноду

Мне на Libraw.su понадобилось отселить переходящую на личности дискуссию, дабы в конкретном обсуждении сохранить высокое отношение сигнал/шум.

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

  • Заводим топик в нужном форуме, запоминаем его Node ID (пусть оно будет 173414).
  • Для каждого из комментариев смотрим его comment-id (администратору он виден в URL ссылок edit/delete) и делаем:
    1. DELETE FROM z_commentsubscribe WHERE cid=ID-комментария; -- сносим подписку, это команда для comment-subcribe, для Comment Notify должно быть как-то похоже
    2. UPDATE comments SET nid=Node-ID WHERE cid=ID-комментария; -- переносим куды следует.
  • Дальше чистим кэши - и все работает.

    Кто бы модуль написал, чтобы у комментария/ветки комментариев появился линк "отнести в отстойник"...

  • Drupal и memcached

    Последние два месяца я собирался прикрутить к Drupal кэширование на memcached. Останавливало меня то, что модуль Memcache был только для Drupal 5.x (у меня используется 6-я версия), а Cache Router был в разобранном неработающем состоянии. Доводить же до ума еще и это место не хотелось.

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

    • Memcache не дал мне заметного прироста производительности, более ~50 запросов в секунду из него вытащить не удалось (а у меня с кэшированием родными средствами Drupal - ну чуть меньше).
    • Cache Router, наоборот, честно все кэширует и скорость работы из кэша - порядка 850-880 req/sec

    Соответственно, поставил я CacheRouter, выглядит работающим.

    Тестирование проводилось путем накатки суточного лога LibRaw.SU утилитой http_load. Считался, естественно, второй проход, подразумевалось что все разлеглось в кэши. Сервер: Dual Opteron 875, FreeBSD 6.4, Postgresql 8.3.5.

    Safaribooks - 2

    Мне кажется про это уже писали в комментах, но я не понял. А получив спам от ACM - понял.

    Для членов ACM доступна сильно урезанная по выбору книжек версия сервиса Safaribooks (про который я уже писал), но зато на халяву (вы платите только за членство в ACM :). Помимо урезанности выбора, нельзя еще скачивать главы в .pdf, что обидно.

    Напоминаю, что если в ACM при регистрации указать, что вы из России (что в моем случае правда), то регистрация будет стоить $35 $43 в год вместо ~$200. Даже не надо притворяться студентом.....

    LibRaw 0.6.2

    По случаю позавчерашнего выхода новой dcraw обновилась и библиотека LibRaw:

    • Поддержка новых камер: Canon G10 and 5D Mark II, Leaf AFi 7, Leica D-LUX4, Panasonic FX150 and G1, Fujifilm IS Pro
    • Изменения в цветовых таблицах для камер из предыдущего апдейта: Canon 50D, Nikon D90 and P6000, Panasonic LX3 and FZ28, Sony A900
    • Исправлена ошибка в обработке файлов Panasonic .RW2, которая проявлялась только на thread-safe версии библиотеки.

    Успешно протестировано, в том числе практически на полном списке файлов от новых камер (кроме Leaf и FX150).

    Скачать можно где всегда. Пользователи KDE тоже уже осчастливлены, но им нужно обновить libkdcraw.

    Оптимальная запись в BTree (Живительная сортировка-2)

    Интересным следствием из оптимальной записи в BTree является то, что кэш практически перестает быть нужен.

    Действительно, нам локально-моментно нужно иметь в кэше по одной странице с каждого уровня дерева плюс место под пару страниц на сплит. Всего получается 4-6 страниц или меньше 50 килобайт для стандартных 8k-страниц.

    Эксперименты подтверждают: уменьшение размера кэша с 100 мегабайт до 128k никак не ухудшают производительность. Даже нет смысла приводить результаты замеров, цифры просто такие же (плюс-минус разумный разброс в пару процентов).

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

    Живительная сортировка

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

    Задача

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

    • 8-байт ключа
    • 20 байт данных на запись
    Эти записи надо сложить в простую базу данных к которой другой код будет доступаться по ключу. Если несколько записей имеют один ключ, то в одну кучку надо сложить все эти записи.

    В качестве хранилища используется BerkeleyDB, формат Btree. Исторически сложилось, не обсуждается, впрочем любые базы данных себя поведут примерно одинаково.

    Кто виноват

    1. Ключей - много. В моем тестовом примере их 18 миллионов, а вообще может быть несколько сотен миллионов (на бОльшие размеры пока рассчитывать не надо).
    2. Ключ - это хороший хэш от строки, поэтому некий код практически является генератором случайных чисел.
    3. Дублирующих ключей (требующих аппенда записи) относительно мало, около 10%, правда есть ключи-рекордсмены, которые повторяются примерно в 0.3% случаев (60 тыс. повторов на 18M).

    В результате, если не делать кэша размером хотя бы с половину базы данных (а делать его разумным, процентов 10-15) и просто писать данные в базу по мере образования, то все происходит довольно медленно: тестовые 18 млн. ключей пишутся в базу на моей тестовой машине около трех часов при размере кэша в 300 мегабайт и базе, дорастающей до 800M. Нет, 1800 транзакций в секунду - это неплохо, но хочется гораздо больше, ибо генерация тестовых данных занимает примерно 3 минуты.

    Причина торможения понятна: если ходить в кэш с random-ключом, то вероятность cache hit примерно равна отношению размера кэша к размеру базы. Пока база маленькая - мы попадаем почти всегда, как только перерастаем кэш, так сразу начинаем изучать время HDD seek вместо более полезного занятия.

    Решение, впрочем, довольно тривиальное.

    noindex-патч для Drupal 6.x, вторая попытка

    В духе нового патча для Movable Type сделал новый nofollow-noindex патч для Drupal 6,x

    1. Сначала надо установить новый вариант предыдущего патча: drupal-noindex-patch2.gz
      После его применения, все страницы, для которых включена фильтрация внешних ссылок, будут иметь ссылки замененными на a href="#link" onClick="return URL-ссылки"
    2. Далее в шаблон страницы, где-то ниже текста комментариев (мы же боремся с ссылками в комментариях, правильно) нужно разместить такой вот javascript-код:
      var links = document.getElementsByTagName('A');
      for(var i=0; i < links.length; i++)
      {
         if(links[i].href.match(/\#link/) && typeof links[i].onclick == 'function'){
              links[i].href=links[i].onclick();        
          }
      }

      После этого наступает счастье: пользователи ничего не замечают (ну, кроме тех, у кого выключен Javascript, у тех после каждой ссылки появляется слово [link]), а поисковые машины индексируют только текст ссылки, но не учитывают ее как ссылку. Чего мы и добивались.

    noindex-патч для MovableType, 4-я попытка

    По совету Николая Сиварева удалось избавиться от главного недостатка моего предыдущего noindex-патча для Movable Type: неудобства при открытии ссылки по правой кнопке.

    Правда патч усложнился и теперь состоит из двух частей.

    1. На Movable Type нужно наложить вот этот вот патч: patch-nofollow-img-js2.gz.
      В результате все внешние ссылки получат вид <a href="#link" onClick="return 'http://link-target';">
    2. В темплейт, где-то в районе footer нужно добавить следующий Javascript-код:
      var links = document.getElementsByTagName('A');
      for(var i=0; i &lt; links.length; i++)
      {
         if(links[i].href.match(/\#link/) && typeof links[i].onclick == 'function'){
              links[i].href=links[i].onclick();        
          }
      }

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

    По совету Николая Сиварева удалось избавиться от главного недостатка моего предыдущего noindex-патча для Movable Type: неудобства при открытии ссылки по правой кнопке.

    Правда патч усложнился и теперь состоит из двух частей.

    1. На Movable Type нужно наложить вот этот вот патч: patch-nofollow-img-js2.gz.
      В результате все внешние ссылки получат вид <a href="#link" onClick="return 'http://link-target';">
    2. В темплейт, где-то в районе footer нужно добавить следующий Javascript-код:
      var links = document.getElementsByTagName('A');
      for(var i=0; i &lt; links.length; i++)
      {
         if(links[i].href.match(/\#link/) && typeof links[i].onclick == 'function'){
              links[i].href=links[i].onclick();        
          }
      }

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

    О сортировке (Ужасы Программирования - 2)

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

    #include "sys/endian.h";
    int cmp(const void *d1,const void *d2)
    {
        uint64_t a1 = be64toh(* ((uint64_t *)d1));
        uint64_t a2 = be64toh(* ((uint64_t *)d2));
        return (a1  > a2) - (a1 < a2);
    }

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

    Ужасы программирования

    Сортирую записи по 8-байтным ключам в byte order (не в numeric). Записей много (сотни миллионов). Оказывается, сравнивать ключи надо так:

        unsigned char *p1 = (unsigned char *)d1;
        unsigned char *p2 = (unsigned char *)d2;
    #define CMP(i) if(p1[i]!=p2[i]) return p1[i]-p2[i]
        CMP(0); CMP(1); CMP(2); CMP(3); CMP(4);CMP(5); CMP(6); CMP(7);
        return 0;
    #undef CMP

    А банальный memcmp/__builtin_memcmp оказывается в 2.2 раза медленнее на общее время исполнения qsort(), во сколько раз различается сравнение - боюсь думать.

    С numeric-сортировкой тоже весело, естественно наступил на (value2-value1) - это быстро и неверно (а верный вариант - получился не быстрее побайтового).

    Pages

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