LINUX.ORG.RU

DMD 2.020 и DMD 1.036

 , ,


0

0

20 октября вышла новая версия компилятора DMD. Наряду с традиционным большим количеством багфиксов есть несколько значительных изменений:

  • В обоих ветках улучшена производительность ассоциативных массивов.
  • Разрешён возврат значений из функций по не-константной ссылке. (Ранее был запрещён вообще)
  • Стандартная библиотека Phobos была отделена от рантайма. Появилась возможность нормально использовать Phobos и Tango в одной программе. Точнее, появится с предстоящим релизом Tango.
Автор предупреждает, что в этом релизе произошло большое количество изменений в коде и вероятно появление ошибок.

>>> Changelog D2

>>> Changelog D1

>>> Подробности

★★★★★

Проверено: Shaman007 ()

Ответ на: комментарий от naryl

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

ну - может тогда слово inline не такая плохая вещь коль это конкурент плюсам? Просто вместо основного хостязыка передаваь строки которые разберуться пусть даже шаблонами. То есть я так понимаю аналогичный ход с нешаблонами не работает, а глядя на реализацию этого редьюса или подобного лично я наблюдаю страшную логику по разбору дочернего языка вместо простой и понятной реализации функциии на хост языке.

r ★★★★★
()
Ответ на: комментарий от naryl

>Кажись где-то ошибка. Либо Collections<Integer>.reduce либо Collections.reduce<Integer>. Или я что-то путаю?

Все правильно. Параметризованный метод.

ident.<Param>method()

r ★★★★★
()
Ответ на: комментарий от naryl

>0_o Они написали ещё один компилятор Java?

Типа того. Но не совсем любой - это как бы expression language для динамического скриптинга. то есть класс задекларировать там нельзя.

r ★★★★★
()
Ответ на: удаленный комментарий

>Прошу уточнить пример.

Пример точный и работающий - методом cut'n'paste.

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

r ★★★★★
()
Ответ на: комментарий от r

Могу даже 2 версии - с BGGA и с JEXL.

r ★★★★★
()
Ответ на: комментарий от r

> лично я наблюдаю страшную логику по разбору дочернего языка

Эм... Где? В std.algorithm.reduce никакого разбора языка нет. Простое и понятное описание действий. Обьявляется NXhelper, применяющий одну функцию для одного массива, проводятся пара тестов на валидность входных данных, определяется возвращаемый тип и применяется NXhelper к каждой паре массив-функция.

naryl ★★★★★
() автор топика
Ответ на: комментарий от naryl

А это я перепутал с binaryFun. Страшный код - там:

typeof({
static ElementType1 a;
static ElementType2 b;
return mixin(comp);
}())
binaryFun(ElementType1, ElementType2)(ElementType1 a, ElementType2 b)
{
return mixin(comp);
}


То есть не то чтобы совсем страшный - но что-то неправильное есть в подобном описании "простых сортировок".

r ★★★★★
()
Ответ на: комментарий от r

> То есть я так понимаю аналогичный ход с нешаблонами не работает

Данный reduce позволяет бОльшую часть работы выполнить при компиляции. Конечно можно все типы заменить на Object, и сделать разбор выражений в рантайме или передачу делегата. Тогда получится те самые JEXL и BGGA соответственно, которые имеем в Java.

naryl ★★★★★
() автор топика
Ответ на: комментарий от r

binaryFun - это просто функция от двух аргументов, которую можно задать и строкой и делегатом.
А реализация у него такая страшная из-за бага в компиляторе №1816. Там же всё написано.

typeof(mixin(comp)) binaryFun(ElementType1, ElementType2)(ElementType1 a, ElementType2 b)
{
    return mixin(comp);
}

Так будет выглядеть код после фикса бага №1816.

naryl ★★★★★
() автор топика
Ответ на: комментарий от naryl

вот реализация на скале:

def reduce[T]( f: (T,T) => T*)( seeds: T* )(l: T*) = {
    val r = Array.concat(seeds);
    for(e <- l; i <- 0 until r.length ) r(i) = f(i)(r(i), e);
    r
}

reduce[Int]((x,y) => x + y, (x,y) => x * y)(0, 1)( 1,2,3,4,5 )

res17: Array[Int] = Array(15, 120)

r ★★★★★
()
Ответ на: комментарий от naryl

К стати какое значение имеют множественные скбоки - только группировочное?
В скале (как и прочих FPL) например можно получить частично параметризованную функцию:

scala> def rsum = = reduce[Int]((x,y) => x + y)(0) _

scala> rsum(1,2,3,4,5)
res23: Array[Int] = Array(15)

r ★★★★★
()
Ответ на: комментарий от r

Со строками использование короче получается почти на десять символов ;)

reduce[Int]((x,y) => x + y, (x,y) => x * y)(0, 1)( 1,2,3,4,5 )
reduce!("a + b", "a * b")(0, 1, [1, 2, 3, 4, 5]);

А вот несколько списков аргументов в scala - это удобно.

Интересно будет сравнить производительность на scala, на D с делегатами и на D со строками.

naryl ★★★★★
() автор топика
Ответ на: комментарий от r

> какое значение имеют множественные скбоки - только группировочное?

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

naryl ★★★★★
() автор топика
Ответ на: комментарий от r

T[] reduce(T)( T delegate (T, T)[] f,  T[] seeds, T[] l) {
    auto r = seeds.dup;
    foreach (i; 0 .. r.length) {
        foreach (e; l) {
            r[i] = f[i](r[i], e); 
        }   
    }   
    return r;
}
void main() {
    auto array = [1, 2, 3, 4, 5];
    alias typeof(array[0]) T;

    auto r = reduce([(T a, T b) { return a + b; }, (T a, T b) { return a * b; }], [0, 1], [1, 2, 3, 4, 5]);
    writefln(r[0]);
    writefln(r[1]);

    auto rsum = (T[] a) { return reduce( [(int a, int b) { return a + b;}], [0], a); };
    writefln(rsum([1, 2, 3, 4, 5]));
}

Выводит:
15
120
[15]

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

naryl ★★★★★
() автор топика
Ответ на: комментарий от r

> это я к тому что там нефиг делать на этапе компиляции

Как минимум проверять соответствие количества seeds количеству функций лучше при компиляции. Но реализация Александреску позволяет, кроме того, передавать строки вместо делегатов. Вдруг кому-то так больше нравится?

naryl ★★★★★
() автор топика
Ответ на: комментарий от naryl

> По шаблонным параметрам вроде можно частично параметризовать.

Нет, нельзя. :(

Разве что для template foo(T1, T2, T3) {...}

Сделать так: template fooif(T) { mixin foo!(int, float, T); }

Впрочем, результат полностью соответствует ожидаемому для любого шаблона foo.

naryl ★★★★★
() автор топика
Ответ на: комментарий от naryl

Надо будет попробовать уломать WB на возврат последнего вычисленного значения из функции... Повсеместные return'ы глаз режут.

naryl ★★★★★
() автор топика
Ответ на: комментарий от naryl

>Как минимум проверять соответствие количества seeds количеству функций лучше при компиляции.

Это в общем случае невозможно.

r ★★★★★
()
Ответ на: комментарий от naryl

>scala безоговорочно выигрывает только в синтаксисе замыканий, и
наличии средства для группировки аргументов

Это не совсем средство группировки - это оптимизированный синтаксис для функции возвращающей функции возвращающей функции..... такой себе карринг- только работу по разбору взял на себя компилятор. Потому частичная параметризация так легко делается. Тип reduce:

[T]((T, T) => T*) => (T*) => (T*) => Array[T]

r ★★★★★
()
Ответ на: комментарий от naryl

> Надо будет попробовать уломать WB на возврат последнего вычисленного значения из функции...

А разве еще есть время? D 2.0 планировался осенью.

tailgunner ★★★★★
()
Ответ на: комментарий от naryl

scala - решение r, приведённое выше.
D делегаты - моё решение, приведённое выше.
D шаблоны - решение Александреску из std.algorithm.

Время компиляции:
scala - 2.71 (fsc неосилил)
D делегаты - 0.09
D шаблоны - 0.12

Время работы для 1.000.000 операций reduce:
scala - 3.36 из них стартап - всего 0.13
D делегаты - 1.02
D шаблоны - 0.03

То же, но с распечаткой каждого значения в /dev/null
scala - 6.46
D делегаты - 1.55
D шаблоны - 0.52

Для D в обоих случаях прибавка ко времени была одинакова, следовательно весь цикл не был "соптимизирован в /dev/null" ни в том ни в другом случае.

Все промежутки - в секундах. Каждый тест проводился 5 раз, приведён лучший результат. программа на scala скомпилена scalac и запущена на sun-jdk-1.6.0.07. D - DMD 2.020. Флаги оптимизации не установлены. (При установке флагов -inline -O D на шаблонах с распечаткой отрабатыает за 0.32)

naryl ★★★★★
() автор топика
Ответ на: комментарий от r

При частичной параметризации время работы программы на scala изменяется в пределах 0.05с в разные стороны для тестов с выводом и без. Значит ли это, что группировка аргументов - не более чем syntactic sugar, или просто пример неудачный?

naryl ★★★★★
() автор топика
Ответ на: комментарий от naryl

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

naryl ★★★★★
() автор топика
Ответ на: комментарий от naryl

>Значит ли это, что группировка аргументов - не более чем syntactic sugar, или просто пример неудачный?

Ну - это синтаксическия сахар вокруг функций возвращающей функцию возвращающей функцию. Там унутри получается грубо говоря 3 аппликации - в D - одна.

r ★★★★★
()
Ответ на: комментарий от r

Впрочем функциональную парадигму и не пытаются причислить к поддерживаемым D.

Результаты теста производительности лучше прокомментируй. Не может Scala в 200 раз медленнее быть. На http://shootout.alioth.debian.org ни по одному тесту нет таких разгромных результатов. Что я сделал не так?

naryl ★★★★★
() автор топика
Ответ на: комментарий от naryl

>Что я сделал не так?

Принципиальная разница в реализации. Функция на D в результате компиляции - это просто одна функция. Да еще учитывая инлайнинги. В скале в данном случае:

1. Все есть first class object включая функции.
2. Сам тип это функция возвращающая функцию врзвращающая функцию.

То есть фактически в каждом цикле инстанции руется три объекта для самого определения редьюса, плюс два объекта для лямбд, плюс обекты для списков - короче в каждом цикле чуть больше чем дохрена сложнее работа происходит.

Если убрать тайп параметр - то быстрее на 25% (за счет отсутствия кучи боксингов в примитивы - операции над примитивными типами в jvm если надо производительность лучше в общем виде не решать с другими типами - будет нагенерено много боксинга. К стати повторное исполнение цикла дает ускорение ~10% за счет джита (на этом коде - более простой у меня ускорился в 3 раза). А если делать не миллион редьюсов, а редьюс миллиона - быстрее на порядок - у меня прыгает с ~3 секунд до ~0.3 секунд - то есть действительно плодиться много объектов. В данном случае речнь не в жаве а в том что все first class object, а поскольку жвм не понимает, что обектами бывает что-то отличное от класса - то Мартину и ребятам пришлось все компилять в классы и как следствие инстанциируется дохрена объектов.

r ★★★★★
()
Ответ на: комментарий от r

Может кто-нибудь scala, если это возможно, под другими vm тестировал?

> а редьюс миллиона - быстрее на порядок


Я делал именно миллион редьюсов. Кстати, дизассемблер показывает, что в результате разворачивания шаблонной реализации Александреску (со строкой) получается цикл с одним call по статическому адресу.

naryl ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.