Match && CIL switch
От: Воронков Василий Россия  
Дата: 21.05.10 20:42
Оценка: 6 (1) +1
Такой вот код на C#:

var x = 0;

switch (x)
{
    case 0: break;
    case 1: break;
    case 2: break;
}


компилируется в:

L_0001: ldc.i4.0 
L_0002: stloc.0 
L_0003: ldloc.0 
L_0004: stloc.1 
L_0005: ldloc.1 
L_0006: switch (L_0019, L_001b, L_001d)
L_0017: br.s L_001f
L_0019: br.s L_001f
L_001b: br.s L_001f
L_001d: br.s L_001f


Match на Немерле:

def x = 0;

match (x) {
    | 0 => {}
    | 1 => {}
    | 2 => {}
}


компилируется в :

L_0002: ldc.i4.0 
L_0003: stloc.0 
L_0004: nop 
L_0005: ldloc.0 
L_0006: ldc.i4.0 
L_0007: bne.un L_0015
L_000c: nop 
L_000d: nop 
L_000e: nop 
L_000f: nop 
L_0010: br L_003e
L_0015: nop 
L_0016: ldloc.0 
L_0017: ldc.i4.1 
L_0018: bne.un L_0026
L_001d: nop 
L_001e: nop 
L_001f: nop 
L_0020: nop 
L_0021: br L_003e
L_0026: nop 
L_0027: ldloc.0 
L_0028: ldc.i4.2 
L_0029: bne.un L_0037
L_002e: nop 
L_002f: nop 
L_0030: nop 
L_0031: nop 
L_0032: br L_003e
L_0037: nop 
L_0038: newobj instance void [Nemerle]Nemerle.Core.MatchFailureException::.ctor()
L_003d: throw 
L_003e: nop 
L_003f: nop


Как говорится, почувствуйте разницу.

Можно ли ожидать, что генерация match-а, когда образцами выступают целые/энумы, будет производиться как в C#?
Очень бы этого хотелось
Re: Match && CIL switch
От: VladD2 Российская Империя www.nemerle.org
Дата: 24.05.10 16:22
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Можно ли ожидать, что генерация match-а, когда образцами выступают целые/энумы, будет производиться как в C#?

ВВ>Очень бы этого хотелось

Всем кроме Камила, который выбросил это (в следствии глючности реализации), все бы этого хотелось.

На скорости рукописного кода это мало сказывается, но генерируемый явно проигрывает.

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

Так что страна ждет своего героя.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Match && CIL switch
От: Воронков Василий Россия  
Дата: 24.05.10 17:02
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Всем кроме Камила, который выбросил это (в следствии глючности реализации), все бы этого хотелось.


Т.е. это было раньше, но открутили?

VD>На скорости рукописного кода это мало сказывается, но генерируемый явно проигрывает.


CIL switch рулит в ряде случаев, в целом не так часто конечно, но вот мне для виртуальной машины очень нужен Например, его большое преимущество — это почти константное время доступа и отсутствие завязки на порядок вхождений.

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

VD>Так что страна ждет своего героя.

То, что это сложно — я понимаю. Судя по всему надо лезть в самые кишки компилятора. А по поводу частного случая не очень понял. C# тоже не во всех случаях использует CIL switch — если у значений идут большие пропуски, то вместо switch-а код может быть скомпилирован в поиск по бинарному дереву или в ту же цепочку переходов. По сути можно и не делать какие-нибудь оптимизации для строк и считать, что если в матче целое или энум, причем "дыр" либо нет вообще, либо они не больше какого-то зашитого значения, то тогда — CIL switch, в противном случае — прежняя логика. Можно даже еще упростить и генерировать CIL switch только для релиза (т.е. не придется делать его дебаг-версию).

Проблема тут в том, что если это будет делать кто-то со стороны, то придется сначала долго и нудно во всем разбираться, а если кто-то, кто уже знает потроха компилятора...
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Re[3]: Match && CIL switch
От: VladD2 Российская Империя www.nemerle.org
Дата: 24.05.10 19:06
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

VD>>Всем кроме Камила, который выбросил это (в следствии глючности реализации), все бы этого хотелось.


ВВ>Т.е. это было раньше, но открутили?


Это было еще до меня. Со слов Камила. Код мол был мутный и глючный. Он сделал тесты которые показали, что компилятор в скорости ничего не теряет если перейти на ифы.

ВВ>CIL switch рулит в ряде случаев, в целом не так часто конечно, но вот мне для виртуальной машины очень нужен Например, его большое преимущество — это почти константное время доступа и отсутствие завязки на порядок вхождений.


Ага. Но весь этот ряд — это генерация свитчей для ДКА.

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


Я тоже "со стороны". В каком-то коде я разобрался. Но в коде который отвечает за преобразование match-а я не силен.

Теоретически за генерацию кода для match-а отвечает DecisionTreeBuilder.n (назавем его "думатель") — это реализация не очень простого алгоритма из ML-я. Общая идея для каждого match-а строится дерево вывода, которое в последствии обрабатывается и заменяется на код. Вот этот код уж генерирует if-ы. Потом где-то в генераторе кода ILEmitter.n по коду порожденному думателем генерируется реальный IL.

Так что начинать нужно с думателя. Я один раз менял его код, но это была косметика (докрутил алгоритм до поддержки паттерн-матчинга по полиморфным типам). Серьезно я в нем не разбирался.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Match && CIL switch
От: Воронков Василий Россия  
Дата: 24.05.10 19:39
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Это было еще до меня. Со слов Камила. Код мол был мутный и глючный. Он сделал тесты которые показали, что компилятор в скорости ничего не теряет если перейти на ифы.


Может, они пытались джамп-таблицу в более сложных случаях генерить? По идее CIL switch должен быть совершенно обособленным сценарием, но судя по тому коду, который ты привел, получается все не так уж легко и просто. Когда работает эмиттер, он разбирает уже только if-ы. Я понимаю, там вот это вот вхождение отвечает за их компиляцию:

/* -- CONDITIONAL CONSTRUCTIONS ------------------------------------ */

/* emits the if/then/else construction */
| If (cond_expr, then_expr, else_expr, then_debug_loc, else_debug_loc) =>
...


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

А можно пойти и другим путем — добавить switch/case и спрятать его куда-нибудь в Nemerle.Optimization. Вообще жаль, что из макросов нельзя генерить IL, тогда бы такие задачи решались без завязки на компилятор.

ВВ>>CIL switch рулит в ряде случаев, в целом не так часто конечно, но вот мне для виртуальной машины очень нужен Например, его большое преимущество — это почти константное время доступа и отсутствие завязки на порядок вхождений.

VD>Ага. Но весь этот ряд — это генерация свитчей для ДКА.

Ну CIL switch рулит если есть некий свитч, который выполняется до фига раз, причем стоимость проверок, которые делал бы if на его месте, заметна на фоне работы остального кода. Пожалуй, таким поведением отличаются именно ДКА.
В компиляторе эта стоимость явно незаметна — до фига чего другого происходит, и лишние проверки оказываются некритичны. А у меня вот если просто вставить одну лишнюю проверку, которая выполняется всегда, то она уже будет весьма заметна глазу по производительности, если запустить какой-нибудь бабл-сорт на 1000 элементов. Что будет, если весь switch заменить на if-ы даже представить страшно.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Re[5]: Match && CIL switch
От: VladD2 Российская Империя www.nemerle.org
Дата: 24.05.10 20:21
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>по хорошему здесь нужен бы отдельный | Switch (...).


Ну, да. Только вот это уже нужно менять тот самый думатель. А там не все так просто.

ВВ>Вообще узнать бы, в чем там были проблемы у них со свитчем.


Напиши Камилу. Он очень хорошо откликается.

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


Насколько я помню проблемы были только с мутностью и бажностью кода.

ВВ>А можно пойти и другим путем — добавить switch/case и спрятать его куда-нибудь в Nemerle.Optimization.


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

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


Вот это не очень разумно. Все же компилятор делает много других обработок. Скажем те же замыкания строит.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Match && CIL switch
От: Воронков Василий Россия  
Дата: 26.05.10 11:21
Оценка:
Здравствуйте, VladD2, Вы писали:

ВВ>>по хорошему здесь нужен бы отдельный | Switch (...).

VD>Ну, да. Только вот это уже нужно менять тот самый думатель. А там не все так просто.

Да уж. Посмотрел я этот думатель. Во-первых мне не очень понятно, каким образом он в принципе используется. Там какая-то мешанина из открытых статических и инстансных методов. Он "на входе" получает цепочку матчей, а "на выходе" отдает структуру Decision? А где тогда формируется дерево, по которому уже идет компиляция через Эмиттер?

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

VD>Насколько я помню проблемы были только с мутностью и бажностью кода.

По поводу мутности не уверен, что тут следует прошедшее время употреблять

ВВ>>А можно пойти и другим путем — добавить switch/case и спрятать его куда-нибудь в Nemerle.Optimization.


VD>Можно сделать стадию оптимизации в которой распозновать такие вот if-ы и генерить для них свитч. Тогда даже написанный вручную if будет соптимизирован если паттерн позволяет.


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

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

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

Ну не макрос. Просто хотелось бы некий механизм для упрощения "расширения" компилятора, чтобы для реализации каких-то фишек не приходилось перелопачивать кучу неочевидного кода. Типа этакого плагина.
Re[7]: Match && CIL switch
От: VladD2 Российская Империя www.nemerle.org
Дата: 26.05.10 14:06
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Да уж. Посмотрел я этот думатель. Во-первых мне не очень понятно, каким образом он в принципе используется.


Ставишь бэйкпоинт и смотришь.

ВВ>Там какая-то мешанина из открытых статических и инстансных методов.


Это общая проблема компилятора. Поляки в начале работы в ООП вообще нихрена не понимали, к сожалению.
Потому и думали переписывать все к едрене матери, чтобы этот бардак не оставлять.

ВВ> Он "на входе" получает цепочку матчей, а "на выходе" отдает структуру Decision? А где тогда формируется дерево, по которому уже идет компиляция через Эмиттер?


Не знаю. Для ответа на этот вопрос мне точно так же придется изучать код и лазить по нему отладчиком.

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

VD>>Насколько я помню проблемы были только с мутностью и бажностью кода.

ВВ>По поводу мутности не уверен, что тут следует прошедшее время употреблять


Там код весьма прозрачный. Не качествненый местами, но более менее. Видимо тот код котором шла речь был вообще за гранью фола.

VD>>Можно сделать стадию оптимизации в которой распозновать такие вот if-ы и генерить для них свитч. Тогда даже написанный вручную if будет соптимизирован если паттерн позволяет.


ВВ>А вот это, мне кажется, может уже и на скорость компиляции заметно повлиять.


Вряд ли.

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


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

Так что тут главный вопрос — это нужно делать (объем работы).

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


Возможно в новой версии компилятора стоит подумать о том чтобы сделать расширяемым не только синтаксис, но и АСТ. А там сделать генерацию кода на базе плагинов будет уже не сложно.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.