dlib 1.7

В рамках Dagon 2.0 скопилось множество улучшений для dlib, и данный релиз подытоживает эту работу.

Добавлен модуль dlib.math.base — замена std.math, которая заменяет некоторые часто используемые функции быстрыми интринсиками LLVM при компиляции LDC (подробнее об этом тут). Ускорены следующие элементарные функции: fabs, sqrt, sin, cos, tan, ceil, floor, round, trunc, rint, nearbyint, pow, exp, exp2, log, log2, log10, fmax, fmin, fma, copysign. В среднем они вдвое быстрее, чем в Phobos. Единственный нюанс, который следует помнить — лучше не импортировать оба модуля одновременно, иначе будет конфликт, и вам придется использовать квалифицированные имена при вызовах.

Добавлена встроенная SIMD-оптимизация для перемножения матриц 4×4 (Matrix4x4f). Это ускоряет оператор в 3-4 раза. В связи с этим удален модуль dlib.math.sse как устаревший, неподдерживаемый и, как выяснилось, нерабочий под x86_64.

Хэш-таблица FlatHashMap из Dagon 2.0 добавлена в библиотеку как dlib.container.hashmap. Реализация xxHash64, соответственно, — как dlib.hash.xxhash64 в новом пакете dlib.hash. Напомню, что это очень быстрая реализация ассоциативных массивов без использования сборщика мусора, которая в десятки раз эффективнее, чем dlib.container.dict и в 1,5-2 раза — чем встроенные ассоциативные массивы D.

Полностью переработан dlib.random — пакет теперь работает на основе перемешанного конгруэнтного генератора (PCG), реализованного для 32- и 64-битных чисел. Это современный эффективный генератор псевдослучайных чисел, который превосходит как Вихрь Мерсенна (std.random), так и линейный конгруэнтный генератор (rand в стандартной библиотеке C). Добавлены новые функции choice (случайный выбор из заданного множества вариантов) and rollDice (случайное целое число от 0 до заданного порога). Функция seed, генерирующая зерно для инициализации генератора из системной энтропии, теперь использует функцию смешивания fmix64 из MurmurHash3 вместо mix Боба Дженкинса.

Не используйте std.random!

Стандартная библиотека использует классический Вихрь Мерсенна (MT19937). Недавно я, вдохновившись эффективностью PCG для шейдерных вычислений, добавил соответствующий модуль в dlib, заменив им rand в dlib.random. Оказалось, что моя функция random для выборки равномерного распределения в диапазоне 0..1 аж в 4 раза быстрее, чем std.random.uniform!

Бенчмарк для 10000000 вызовов:

std.random.uniform: 77 ms, 38 μs, and 3 hnsecs total
dlib.random.random: 19 ms, 599 μs, and 3 hnsecs total

Стандартное отклонение у обеих функций примерно одинаковое:

std.random.uniform: 0.544σ
dlib.random.random: 0.413σ

Обновления

dlib 1.3.0

Вышла новая версия dlib. В библиотеке появился новый пакет dlib.math.random с реализацией генератора псевдослучайных чисел на основе C-функции rand. Проделан ряд улучшений в математическом пакете: добавлена поддержка компилятора GDC в модуль dlib.math.sse, появилась новая функция интерполяции bezierQuadratic.

Количество скачиваний dlib в реестре DUB достигло 1400 в месяц — рекордный показатель за все время существования проекта!

Подготовка к релизу Dagon 0.16

Новая версия Dagon планируется к выпуску совсем скоро — на днях внес ряд багфиксов и улучшений в физику Newton (в частности, исправлен прыжок контроллера персонажа на плоских поверхностях), а также добавил встроенную функцию создания скриншотов — Application.takeScreenshot.

Журнал «FPS» №26

Вышел 26 номер электронного PDF-журнала «FPS», посвященного разработке игр, программированию, компьютерной графике и звуку.

Читайте в этом номере:

> Tube Open Movie. Интервью с Бассамом Курдали
> Обзор дополнений Blender, выпуск 5
> GIMP: ломо-эффект как в Instagram
> Физический движок своими руками, часть III
> Making-of: логическая мини-игра Arrow
> Генерация случайных уровней
> Осваиваемся в SDL2
> Пишем плагин для DeleD на D
> Как я стал D-шником или Путь художника в IT
> Игровые новости из мира СПО и Linux
> «Корпорация зла». Почему у Microsoft нет будущего

Номер доступен для онлайн-чтения и загрузки на сервисе Issuu.com, Документах Google и Dropbox.

Последние новости по проекту вы можете узнать в публичной странице журнала в социальной сети Google+: http://gplus.to/fpsmag. Добавляйте нас в круги, оставляйте свои комментарии и отписывайтесь в нашем сообществе.

Архив номеров журнала здесь.

Случайная выборка с учетом веса

Один из распространенных приемов в игровой логике – использование элемента случайности. Он используется, например, при машинной генерации уровней, лабиринтов, или когда на локации появляются случайные враги или бонусы. При этом зачастую требуется выбрать случайный объект из какого-либо списка с учетом того, что некоторые из них имеют большую вероятность выбора, чем другие – то есть, имеют больший “вес”.

Я написал особую реализацию алгоритма такой выборки – она работает не с обычными массивами, а с перечислениями (enum). В шаблон функции передаются два перечисления – самих элементов и их весов. Этот пример иллюстрирует также богатые возможности метапрограммирования, CTFE и интроспекции в D.

import std.stdio;
import std.traits;
import std.random;
import std.algorithm;

T weightedRandomEnum(T, W)()
    if (isNumeric!W &&
        is(T == enum) && is(W == enum) && 
        EnumMembers!T.length == EnumMembers!W.length)
{
    enum members = [EnumMembers!T];
    enum weights = [EnumMembers!W];
    enum weightsSum = reduce!("a + b")([EnumMembers!W]);
    
    auto randomNumber = uniform(0, weightsSum);
    
    foreach(i, weight; weights)
    {
        if (randomNumber < weight)
            return members[i];
        else
            randomNumber -= weight;
    }
    
    assert(0, "Should never get here");
}

enum Color
{
    Red, Yellow, Green, Blue
}

enum Weights
{
    Red = 100, 
    Yellow = 20, 
    Green = 20, 
    Blue = 5
}

void main()
{
    foreach(i; 0..10)
        writeln(weightedRandomEnum!(Color, Weights));
}