Feel Good.

30 декабря 2010

Строим идентификатор для множества

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

Сформулируем требование следующим образом: найти такой оператор F, что для любого набора (u, v, ...) будет выполнено:
F(u, v, ...)= F(v, u, ...)=F(всевозможные перестановки) (условие коммутативности), причем не существует любого другого элемента z != u, такого что выполняется:
F(u, v, ...)=F(z, v, ...)=F(всевозможные перестановки) (условие уникальности)*.
Или более привычно: u, v, ... являются простыми ключами, а F(u, v, ...) составным ключом в единственном числе.

22 декабря 2010

Используем Reflection в T4 (Text Template Transformation Toolkit)

Недавно, мне была поставлена следующая задача: для каждого класса из стороннего API, разработать обертку (wrapper class), для удобства использования стороннего API. Оптимальное решение подобных задач всегда использовать кодогенерацию, а наиболее удобный инструмент для этого, это T4 (Text Template Transformation Toolkit). Так как набор классов находился в уже скомпилированной сборке, то действовать надо было только через System.Reflection. Как выяснилось позже, что при работе со сборкой через reflection в T4 возникает проблема блокировки, загружаемой через Assembly.Load, сборки. Stackoverflow подсказал, что для решения данной проблемы нужно воспользоваться FxCop API, предоставляющий достаточный инструментарий для работы со сборкой на уровне Reflection.

17 ноября 2010

False sharing

Казалось бы, зачем задумывываться о процессах, происходящих на таком низком уровне, как кэширование данных в L1 и L2 кешах (L1, L2 cache), если Вы программируете под .NET. Очевидно для повышения быстродействия программы (perfomance) за счет уменьшения кэш-промахов (Cache Miss). Самый простой и классический пример демонстрирующий проблему Cache Miss, это "неправильный" обход массива. При "правильном" обходе количество промахов будет минимально, следовательно участок кода выполнится быстрее:

int size = 10000;

int[,] matrix = new int[size, size];

 

// Вариант 1

// Очень медленный вариант

for (int col = 0; col < size; col++)

    for (int row = 0; row < size; row++)

        matrix[row, col] = 0;

 

// Вариант 2

// Быстрый вариант

for (int row = 0; row < size; row++)

    for (int col = 0; col < size; col++)

        matrix[row, col] = 0;