CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 12.09.10 18:05
Оценка: 224 (8)
Сейчас в репозитории есть ветка cil_switch в которой ведется работа над реализацией сопоставления с образцом на основе опкода SWITCH.
Предлагаю протестировать производительность match-а ревизии r9137 (более поздние требуют изменения исходников для полного 4-стадийного билда).
Опкод SWITCH генерируется для значений интегральных типов, влезающих в System.Int32 и вариантов, enum-ы пока не поддерживаются (ведем охоту на ведьм).

З.Ы. Другая хорошая новость Nemerle.Compiler.dll проходит тесты PEVerify.
/* иЗвиНите зА неРовнЫй поЧерК */
Re: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 13.09.10 15:05
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Предлагаю протестировать производительность match-а ревизии r9137 (более поздние требуют изменения исходников для полного 4-стадийного билда).


Забавно, но в этом тесте с вариантой размером 9 разницы с прежним каскадом условий совершенно никакой нет. Возможно на таких объемах вызов _N_GetVariantCodeSafe / _N_GetVariantCode съедает весь профит.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[2]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 13.09.10 15:35
Оценка:
Здравствуйте, hardcase, Вы писали:

H>>Предлагаю протестировать производительность match-а ревизии r9137 (более поздние требуют изменения исходников для полного 4-стадийного билда).


H>Забавно, но в этом тесте с вариантой размером 9 разницы с прежним каскадом условий совершенно никакой нет. Возможно на таких объемах вызов _N_GetVariantCodeSafe / _N_GetVariantCode съедает весь профит.


Кстати, у меня тут была одна идея... Вместо использования виртуального метода можно в каждый вариант (в базовый тип) добавлять поле типа int (или даже byte) и инициализировать его для каждого своим значением, и проверять потом именно его.

Это немного увеличит объем памяти занимаемый вариантами и потребует лишний инструкции при создании их экземпляров, но возможно это увеличит скорость ПМ.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 14.09.10 05:58
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Сейчас в репозитории есть ветка cil_switch в которой ведется работа над реализацией сопоставления с образцом на основе опкода SWITCH.


Ветка интегрирована в trunk.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[2]: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 14.09.10 10:36
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Здравствуйте, hardcase, Вы писали:


H>>Сейчас в репозитории есть ветка cil_switch в которой ведется работа над реализацией сопоставления с образцом на основе опкода SWITCH.


H>Ветка интегрирована в trunk.


Сужение области применимости этой оптимизации (матч на 12 и более вариантов использует switch, остальные — if-ы) ускорило компиляцию на ~4-5сек (/t:Stage1 /p:Configuration=Release).
/* иЗвиНите зА неРовнЫй поЧерК */
Re[3]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 14.09.10 11:09
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Сужение области применимости этой оптимизации (матч на 12 и более вариантов использует switch, остальные — if-ы) ускорило компиляцию на ~4-5сек (/t:Stage1 /p:Configuration=Release).


Ключик бы добавить типа forceSwitch — чтобы можно было и для небольшого кол-ва вхождений использовать именно Switch.
Re[4]: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 14.09.10 11:21
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Ключик бы добавить типа forceSwitch — чтобы можно было и для небольшого кол-ва вхождений использовать именно Switch.


В текущей реализации это бессмысленно. Для матчей меньше 10-15 штук свич только замедляет код.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[5]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 14.09.10 13:27
Оценка:
Здравствуйте, hardcase, Вы писали:

ВВ>>Ключик бы добавить типа forceSwitch — чтобы можно было и для небольшого кол-ва вхождений использовать именно Switch.

H>В текущей реализации это бессмысленно. Для матчей меньше 10-15 штук свич только замедляет код.

Почему? Как тестируешь?
Если в Шарпе свитч на 10 элементов прогнать, скажем, миллион раз, то он будет заметно быстрее аналогичной конструкции на ифах, если выбираемое вхождение находится ближе к концу (т.е. чтобы в него попасть, приходится пройти через цепочку проверок).

Кстати, есть ли тесты, на которых текущая реализация Свитча оказывается быстрее Иф-ов?
Re[6]: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 14.09.10 13:42
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Здравствуйте, hardcase, Вы писали:


ВВ>>>Ключик бы добавить типа forceSwitch — чтобы можно было и для небольшого кол-ва вхождений использовать именно Switch.

H>>В текущей реализации это бессмысленно. Для матчей меньше 10-15 штук свич только замедляет код.

ВВ>Почему? Как тестируешь?

ВВ>Если в Шарпе свитч на 10 элементов прогнать, скажем, миллион раз, то он будет заметно быстрее аналогичной конструкции на ифах, если выбираемое вхождение находится ближе к концу (т.е. чтобы в него попасть, приходится пройти через цепочку проверок).

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

Целые числа даже не стал тестировать — там тривиально.

ВВ>Кстати, есть ли тесты, на которых текущая реализация Свитча оказывается быстрее Иф-ов?


Более 10-12 вхождений для вариантов, но это эвристика полученная экспериментами с компилятором.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[7]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 14.09.10 13:50
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Я тестирую матчинг на вариантах. Тест, где последовательные isinst рвут свич в текущей реализации я привел во втором посте.

H>Тестирую компилятором, ибо это интереснее всего.
H>Целые числа даже не стал тестировать — там тривиально.

Однако для целых чисел преимущество свитча может быть видно и на <= 12 элементов, так что ключик бы не помешал.
К тому же преимущество CIL Switch — это не всегда скорость, а зачастую отсуствие завязки на последовательность вхождений — т.е. от "перестановки слагаемых" у нас скорость исполнения не меняется, что иногда важно.

Вообще этот switch нужен для весьма специфических сценариев, зачем там вообще варианты
Re[8]: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 14.09.10 13:52
Оценка: +1
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Здравствуйте, hardcase, Вы писали:


H>>Я тестирую матчинг на вариантах. Тест, где последовательные isinst рвут свич в текущей реализации я привел во втором посте.

H>>Тестирую компилятором, ибо это интереснее всего.
H>>Целые числа даже не стал тестировать — там тривиально.

ВВ>Однако для целых чисел преимущество свитча может быть видно и на <= 12 элементов, так что ключик бы не помешал.


А я не говорил что для чисел используется 12 вхождений. Для них порог сейчас 5.

ВВ>К тому же преимущество CIL Switch — это не всегда скорость, а зачастую отсуствие завязки на последовательность вхождений — т.е. от "перестановки слагаемых" у нас скорость исполнения не меняется, что иногда важно.


Я прекрасно понимаю для чего нужен switch — для константного времени выбора действия. Так вот это константное время для матчинга по вариантам оправдывается лишь при достаточно большом их количестве.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[9]: CIL switch и сопоставление с образцом
От: Ka3a4oK  
Дата: 14.09.10 13:59
Оценка:
H>Я прекрасно понимаю для чего нужен switch — для константного времени выбора действия.
Может логарифмического?
Re[9]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 14.09.10 14:00
Оценка:
Здравствуйте, hardcase, Вы писали:

ВВ>>Однако для целых чисел преимущество свитча может быть видно и на <= 12 элементов, так что ключик бы не помешал.

H>А я не говорил что для чисел используется 12 вхождений. Для них порог сейчас 5.

Откуда вообще возникла необходимость в этом порогое? C# без него обходится как-то.

ВВ>>К тому же преимущество CIL Switch — это не всегда скорость, а зачастую отсуствие завязки на последовательность вхождений — т.е. от "перестановки слагаемых" у нас скорость исполнения не меняется, что иногда важно.

H>Я прекрасно понимаю для чего нужен switch — для константного времени выбора действия. Так вот это константное время для матчинга по вариантам оправдывается лишь при достаточно большом их количестве.

Где ваши доказательства? Я вполне могу себе представить стейт-машину с 3-4 состояниями, где отсутствие связи между порядков вариантом и скоростью выбора не помешало бы.
Re[10]: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 14.09.10 14:00
Оценка:
Здравствуйте, Ka3a4oK, Вы писали:

H>>Я прекрасно понимаю для чего нужен switch — для константного времени выбора действия.

KK>Может логарифмического?

Нет. Константного.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[10]: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 14.09.10 14:03
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Где ваши доказательства? Я вполне могу себе представить стейт-машину с 3-4 состояниями, где отсутствие связи между порядков вариантом и скоростью выбора не помешало бы.


Отлично, я раз за тебя. А теперь взгляни на начальное сообщение топика:

Предлагаю протестировать производительность match-а ревизии r9137 (более поздние требуют изменения исходников для полного 4-стадийного билда).


Если тебе интересная такая машина — организуй тесты, вместе на них посмотрим.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[10]: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 14.09.10 14:06
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Здравствуйте, hardcase, Вы писали:


ВВ>>>Однако для целых чисел преимущество свитча может быть видно и на <= 12 элементов, так что ключик бы не помешал.

H>>А я не говорил что для чисел используется 12 вхождений. Для них порог сейчас 5.

ВВ>Откуда вообще возникла необходимость в этом порогое? C# без него обходится как-то.


Из-за того, что алгоритм построения TExpr.Switch един для вариантов и интегральных типов (compile_switch). Параметр нужно было специфицировать.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[11]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 14.09.10 14:19
Оценка:
Здравствуйте, hardcase, Вы писали:

H>

Предлагаю протестировать производительность match-а ревизии r9137 (более поздние требуют изменения исходников для полного 4-стадийного билда).

H>Если тебе интересная такая машина — организуй тесты, вместе на них посмотрим.

А что там организовывать? Создай матч на целые из четырех вхождений, всегда выбирается 3-е или 4-е вхождение, код самих вхождений по скорости выполнения аналогичен скорости потенциальных проверок. Ну и завернуть все это, скажем, в цикл на 10 миллионов итераций. Все сразу будет видно.
Re[11]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 14.09.10 14:20
Оценка:
Здравствуйте, hardcase, Вы писали:

ВВ>>Откуда вообще возникла необходимость в этом порогое? C# без него обходится как-то.

H>Из-за того, что алгоритм построения TExpr.Switch един для вариантов и интегральных типов (compile_switch). Параметр нужно было специфицировать.

Ничего не понял. Ты имеешь в виду, что тебе нужно знать размер джамп-таблицы? А причем тут это?
Re[11]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 14.09.10 14:28
Оценка:
Здравствуйте, hardcase, Вы писали:

H>>>Я прекрасно понимаю для чего нужен switch — для константного времени выбора действия.

KK>>Может логарифмического?
H>Нет. Константного.

Вообще-то в строгом смысле у свитча не константное время. Константное время означает, что для свитча с любым количеством элементов скорость доступа к конкретному элементу будет одинакова. Это не так.
У свитча доступ к элементу не зависит от порядка элементов. В реальном же коде может оказаться, что выбор варианта через бинарный поиск будет быстрее свитча.
Re[3]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.09.10 14:28
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Сужение области применимости этой оптимизации (матч на 12 и более вариантов использует switch, остальные — if-ы) ускорило компиляцию на ~4-5сек (/t:Stage1 /p:Configuration=Release).


А другие константы пробовал? Скажем 5 или 7?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.09.10 14:30
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Если в Шарпе свитч на 10 элементов прогнать, скажем, миллион раз, то он будет заметно быстрее аналогичной конструкции на ифах, если выбираемое вхождение находится ближе к концу (т.е. чтобы в него попасть, приходится пройти через цепочку проверок).


Это языком. А ты попробуй на практике. Причем с аналогом вариантов.

ВВ>Кстати, есть ли тесты, на которых текущая реализация Свитча оказывается быстрее Иф-ов?


Тебе же сказали при К > 11.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.09.10 14:34
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Целые числа даже не стал тестировать — там тривиально.


А зря. Для них может оказаться совсем другой расклад. Я думаю для них К > 4 уже может дать выигрыш.
А учитывая то, что именно целые важны для оптимизации разных там ДКА — это становится весьма важным вопросом.

H>Более 10-12 вхождений для вариантов, но это эвристика полученная экспериментами с компилятором.


Опять же на задачах типа генерируемых ДКА — это может быть не так.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: CIL switch и сопоставление с образцом
От: Ka3a4oK  
Дата: 14.09.10 14:41
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Здравствуйте, Ka3a4oK, Вы писали:


H>>>Я прекрасно понимаю для чего нужен switch — для константного времени выбора действия.

KK>>Может логарифмического?

H>Нет. Константного.


Не понимать. Я вижу два варианта с приемлемым потреблением памяти:
1. Цепочка ифов, т.е. линейный поиск (время O(n))
2. Бинарный поиск по множеству значений (время O(log n))

Во что в итоге превратится следующая конструкция?

match(x)
{
|1 =>...
|5 =>...
|20 =>...
|500 =>...
|3000 =>...
|16365 =>...
}
Re[7]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 14.09.10 14:46
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Воронков Василий, Вы писали:

ВВ>>Если в Шарпе свитч на 10 элементов прогнать, скажем, миллион раз, то он будет заметно быстрее аналогичной конструкции на ифах, если выбираемое вхождение находится ближе к концу (т.е. чтобы в него попасть, приходится пройти через цепочку проверок).
VD>Это языком.

Язык — это главный инструмент программиста. Особенно РСНД-нера

VD>А ты попробуй на практике. Причем с аналогом вариантов.


Варианты меня мало интересуют в данном вопросе.
Касательно целых — если сравнивать именно Свитч и *цепочку ифов*, то результат будет прекрасно виден и на таком коде:

for (var i = 0; i < ITER; i++)
{
    switch (x)
    {
        case 0: y += 0; break;
        case 1: y += 1; break;
        case 2: y += 2; break;
        case 3: y += 3; break;
        case 4: y += 4; break;
    }
}


Где ITER равен, скажем, 10*1000*1000.
Если же сравнивать свитч и то, что наколдовал компилятор при трансляции цепочки иф-ов в релизе, то результат может быть какой угодно. Вопрос — что мы сравниваем?

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

А вот если дать компилятору обухом по голове, чтобы он иф-ы не трогал, то результат получается очень даже убедительным:

class Program
{
    static void Main(string[] args)
    {
        var ITER = 1000*1000*1000;
        var x = 3;

        var y = 0;
        x = GetX();
        var dt = DateTime.Now;
        
        for (var i = 0; i < ITER; i++)
        {
            switch (x)
            {
                case 0: y += 0; break;
                case 1: y += 1; break;
                case 2: y += 2; break;
                case 3: y += 3; break;
                case 4: y += 4; break;
            }
        }

        Console.WriteLine("Switch: {0}", DateTime.Now - dt);

        y = 0;
        x = GetX2();
        dt = DateTime.Now;

        for (var i = 0; i < ITER; i++)
        {
            if (x == 0) {
                y += 0;
            }
            else if (x == 1) {
                y += 1;
            }
            else if (x == 2) {
                y += 2;
            }
            else if (x == 3) {
                y += 3;
            }
            else if (x == 4) {
                y += 4;
            }
        }

        Console.WriteLine("If: {0}", DateTime.Now - dt);
    }


    static int GetX() { return 3; }
    static int GetX2() { return Int32.Parse("3"); }
}


В релизе выдает:

Switch: 00:00:00.4687710
If: 00:00:04.1564968


Разница на порядок однако.
Re[12]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.09.10 14:47
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

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

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

В двух словах — полный бред.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 14.09.10 14:48
Оценка:
Здравствуйте, VladD2, Вы писали:

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

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

Ты с чем-то не согласен?
Re[12]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.09.10 14:50
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>А что там организовывать? Создай матч на целые из четырех вхождений, всегда выбирается 3-е или 4-е вхождение, код самих вхождений по скорости выполнения аналогичен скорости потенциальных проверок. Ну и завернуть все это, скажем, в цикл на 10 миллионов итераций. Все сразу будет видно.


Отличный подход для измерения сфероконей вакуумных.

Вот только они никому не интересны. Интересны реальные задачи. А на реальных задачах применение свитчей всегда дает проигрыш во времени. Причем если в релизе он мелкий, то в дебаге уже более заметный.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[12]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 14.09.10 14:51
Оценка:
Здравствуйте, Ka3a4oK, Вы писали:

KK>Во что в итоге превратится следующая конструкция?


Свитч — это оп-код такой в МСИЛе. Формирует джамп-таблицу. Джамп-таблицу с таким дырами, как в твоем примере, генерировать никто в здравом уме не будет. Компилятор Шарпа использует и 1) и 2), в зависимости от ситуации. Немерл, как я понимаю, только 1).
Re[14]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.09.10 14:53
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

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

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

ВВ>Ты с чем-то не согласен?


Да. Со всеми твоим словами прорепетированными выше. Время конечно константное. И бинарный поиск никак не может быть быстрее прямой индексации.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 14.09.10 14:53
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Вот только они никому не интересны. Интересны реальные задачи. А на реальных задачах применение свитчей всегда дает проигрыш во времени. Причем если в релизе он мелкий, то в дебаге уже более заметный.


С чего бы это?
На 99% реальных задач разницы во времени видно попросту не будет, что там свитч, что цепочка ифов.
Re[15]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 14.09.10 14:55
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Да. Со всеми твоим словами прорепетированными выше. Время конечно константное. И бинарный поиск никак не может быть быстрее прямой индексации.


Фига. Любое измерение скорости в данном случае предполагает, что придется свитч заворачивать в цикл — что в общем и является реальными случаем использования в случае с теми же ДКА, — и тут вылезает интересный момент: чем больше свитч, тем больше времени уходит на загрузку самой джамп-таблицы, что как раз и делает оба моих утверждения верными в реальной жизни.
Re[8]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.09.10 15:04
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Язык — это главный инструмент программиста. Особенно РСНД-нера




ВВ>Варианты меня мало интересуют в данном вопросе.


Ну, а что тогда в разговор лезешь? Тут как раз речь в основном о них идет.

ВВ>Касательно целых — если сравнивать именно Свитч и *цепочку ифов*, то результат будет прекрасно виден и на таком коде:


ВВ>
ВВ>for (var i = 0; i < ITER; i++)
ВВ>{
ВВ>    switch (x)
ВВ>    {
ВВ>        case 0: y += 0; break;
ВВ>        case 1: y += 1; break;
ВВ>        case 2: y += 2; break;
ВВ>        case 3: y += 3; break;
ВВ>        case 4: y += 4; break;
ВВ>    }
ВВ>}
ВВ>


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

ВВ>Где ITER равен, скажем, 10*1000*1000.


Да хоть миллиард. Современные процессоры так устроены, что они будут отлично предсказывать переход. И получишь ты производительность тестового случая. А вот в реальных условиях все будет совсем не так.

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


Скорость конечного приложения. Это если говорить о нас.

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


Мы и понимаем. Потому тестируемся на компиляции компилятора. Где много разного кода.

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


ВВ>
ВВ>            switch (x)
ВВ>            {
ВВ>                case 0: y += 0; break;
ВВ>                case 1: y += 1; break;
ВВ>                case 2: y += 2; break;
ВВ>                case 3: y += 3; break;
ВВ>                case 4: y += 4; break;
ВВ>            }
...
ВВ>            if (x == 0) {
ВВ>                y += 0;
ВВ>            }
ВВ>


ВВ>В релизе выдает:


ВВ>
ВВ>Switch: 00:00:00.4687710
ВВ>If: 00:00:04.1564968
ВВ>


Меня тут больше интересуют друге вопросы.
1. Как у тебя этот код вообще (без дефолта) скомпилировался?
2. Что вызывается на пятой и последующих итерациях?
3. Зачем у ифов бессмысленные скобки?

ВВ>Разница на порядок однако.


Меня порядки сфероконей не интересуют даже если они не находятся в вакууме.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[16]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.09.10 15:08
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

VD>>Да. Со всеми твоим словами прорепетированными выше. Время конечно константное. И бинарный поиск никак не может быть быстрее прямой индексации.


ВВ>Фига. Любое измерение скорости в данном случае предполагает, что придется свитч заворачивать в цикл


Тоже мимо. Можно поступать проще. Есть реальные приложения. Можно измерять их конечную скорость.

В прочем я говорил о твоих словах. Свитч таки имеет константное время (проверка + индексированный доступ). И никакой бинарный поиск не может с ним конкурировать.

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


Ошибочны твои утверждения. Все таблицы попадают в память еще при компиляции (джитом или нгеном). Таблицы не влезающих в кэши современных процессоров я себе даже представить боюсь.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 14.09.10 15:10
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Ну, а что тогда в разговор лезешь? Тут как раз речь в основном о них идет.


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

ВВ>>
ВВ>>for (var i = 0; i < ITER; i++)
ВВ>>{
ВВ>>    switch (x)
ВВ>>    {
ВВ>>        case 0: y += 0; break;
ВВ>>        case 1: y += 1; break;
ВВ>>        case 2: y += 2; break;
ВВ>>        case 3: y += 3; break;
ВВ>>        case 4: y += 4; break;
ВВ>>    }
ВВ>>}
ВВ>>

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

Посмотри код внимательно, свитч идет не по переменной цикла.

ВВ>>Где ITER равен, скажем, 10*1000*1000.

VD>Да хоть миллиард. Современные процессоры так устроены, что они будут отлично предсказывать переход. И получишь ты производительность тестового случая. А вот в реальных условиях все будет совсем не так.

Как и в любом тесте

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

VD>Скорость конечного приложения. Это если говорить о нас.

Компилятор ваш, если верить Камиллу, плохой пример для тестирования преимущества свитчей — ведь это уже тестировали до вас и преимуществ не выяснили, разве нет?
Опять же — ну получите вы скорость одного конечного приложения — что это скорость будет говорить о скорости других приложений?

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


VD>Мы и понимаем. Потому тестируемся на компиляции компилятора. Где много разного кода.


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


ВВ>>
ВВ>>            switch (x)
ВВ>>            {
ВВ>>                case 0: y += 0; break;
ВВ>>                case 1: y += 1; break;
ВВ>>                case 2: y += 2; break;
ВВ>>                case 3: y += 3; break;
ВВ>>                case 4: y += 4; break;
ВВ>>            }
VD>...
ВВ>>            if (x == 0) {
ВВ>>                y += 0;
ВВ>>            }
ВВ>>


ВВ>>В релизе выдает:


ВВ>>
ВВ>>Switch: 00:00:00.4687710
ВВ>>If: 00:00:04.1564968
ВВ>>


VD>Меня тут больше интересуют друге вопросы.

VD>1. Как у тебя этот код вообще (без дефолта) скомпилировался?

Это С#. Все прекрасно компилируется. В чем проблема?

VD>2. Что вызывается на пятой и последующих итерациях?


Вызывается всегда один и тот же case 3. Выборка идет не по переменной цикла, а по переменной х.

VD>3. Зачем у ифов бессмысленные скобки?




ВВ>>Разница на порядок однако.

VD>Меня порядки сфероконей не интересуют даже если они не находятся в вакууме.

Хех, ты даже код внимательно не посмотрел.
Re[4]: CIL switch и сопоставление с образцом
От: Аноним  
Дата: 14.09.10 15:12
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, hardcase, Вы писали:


H>>Сужение области применимости этой оптимизации (матч на 12 и более вариантов использует switch, остальные — if-ы) ускорило компиляцию на ~4-5сек (/t:Stage1 /p:Configuration=Release).


VD>А другие константы пробовал? Скажем 5 или 7?


Нет. Меня больше варианты интересуют. Параметр просто от балды поставил, прикинув количество потенциальных арифметических операций для вычисления перехода.
4 последовательных числа будут также последовательно сравниваться (ок, параметр можно поправить), 5 уже будут в switch превращаться.

H>>Нет. Константного.


KK>Не понимать. Я вижу два варианта с приемлемым потреблением памяти:

KK>1. Цепочка ифов, т.е. линейный поиск (время O(n))
KK>2. Бинарный поиск по множеству значений (время O(log n))

А я вижу в построении таблицы переходов (грубо и абстрактно):

index — индекс в таблице переходов.
br_size — длина инструкции BR с адресом:
jump index * br_size //переходим на index * br_size байт вперед, попадая на одну из jump-кейзов
jump case0  // переход на код кейза 0
jump case1  // переход на код кейза 1 и т.д.
jump case2
jump case3
...

З.Ы. могу заблуждаться в своих суждениях.


KK>Во что в итоге превратится следующая конструкция?


KK>
KK>match(x)
KK>{
KK>|1 =>...
KK>|5 =>...
KK>|20 =>...
KK>|500 =>...
KK>|3000 =>...
KK>|16365 =>...
KK>}
KK>


Эта конструкция превратится в цепочку сравнений. Но, если народ настаивает, могу сделать и бинарный поиск.
Re[17]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 14.09.10 15:12
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Тоже мимо. Можно поступать проще. Есть реальные приложения. Можно измерять их конечную скорость.

VD>В прочем я говорил о твоих словах. Свитч таки имеет константное время (проверка + индексированный доступ). И никакой бинарный поиск не может с ним конкурировать.

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

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

VD>Ошибочны твои утверждения. Все таблицы попадают в память еще при компиляции (джитом или нгеном). Таблицы не влезающих в кэши современных процессоров я себе даже представить боюсь.

Ну тест, проводенный мной года два назад, как раз показал, что при серьезном распухании свитчей время сильно уплывает. Надо проверить еще раз, есть подозрение, что таблица все же загружается на лету.
Re[14]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.09.10 15:13
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>На 99% реальных задач разницы во времени видно попросту не будет, что там свитч, что цепочка ифов.


Ну, вот на одной реальной задаче — компиляции вручную написанного компилятора разница есть. Не очень большая, но таки есть. Лобовой вариант — генерация свтича (для вариантов) для трех и более последовательно идущих элементов дает замедление на 5 секунд в релизе (и намного более существенное в дебаге). Оптимизация для 12 последовательно идущих элементов дает 5 секунд выигрыша.

С целыми расклад несколько другой. Там нет проверок на null которые есть при переходе по вариантам имеющим умолчальное вхождение match-а. Там хардкейс выбрал константу — 5. Видимо тесты показали, что так оно эффективнее.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[15]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 14.09.10 15:15
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Воронков Василий, Вы писали:

ВВ>>На 99% реальных задач разницы во времени видно попросту не будет, что там свитч, что цепочка ифов.
VD>Ну, вот на одной реальной задаче — компиляции вручную написанного компилятора разница есть. Не очень большая, но таки есть. Лобовой вариант — генерация свтича (для вариантов) для трех и более последовательно идущих элементов дает замедление на 5 секунд в релизе (и намного более существенное в дебаге). Оптимизация для 12 последовательно идущих элементов дает 5 секунд выигрыша.

Замедление чего? Времени компляции компилятора? Времени компиляции самим компилятором? Компиляции чего? Самого компилятора?
Re[18]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.09.10 15:22
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

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


Похоже у тебя давно не было плодотворных дискуссий (тобишь — флэймов). Только вот мне в них влезать не охота. Так что последний раз отвечаю. Не понял, твои проблемы.

1. Никакой загрузки во время выполнения быть не должно. Таблицы должны формироваться и помещаться в память при джитае или нгене.
2. Даже если такое есть, то время все равно будет константным, так как под константностью времени понимают одинаковое время на поиск любого элемента присутствующего в таблице. Учитывая что таблицу нужно (или не нужно) грузить каждый раз, время по любому будет одинаковым.

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

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

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

Так что константный != быстрый. Мы же хотим иметь более высокую скорость работы обычных приложений.

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


Проверяй.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.09.10 15:35
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

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


Хардкейс же тебе сказал, что для целых ограничение другое.

ВВ>Посмотри код внимательно, свитч идет не по переменной цикла.


ОК, но оно константное. Тогда он вообще может быть заинлайнен с полным устранением свитча.

ВВ>Как и в любом тесте


Потому их нужно в треш отправить. А тесты проводить на реальных приложениях.

ВВ>Компилятор ваш, если верить Камиллу, плохой пример для тестирования преимущества свитчей — ведь это уже тестировали до вас и преимуществ не выяснили, разве нет?


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

ВВ>Опять же — ну получите вы скорость одного конечного приложения — что это скорость будет говорить о скорости других приложений?


Извини, но спорить ради спора у меня желания нет. Думаю, что мою позицию ты понял. Доказывать тебе что-то я не имеют никакого желания. Будешь делать свой компилятор, поступай как считаешь нужным.

VD>>Меня тут больше интересуют друге вопросы.

VD>>1. Как у тебя этот код вообще (без дефолта) скомпилировался?

ВВ>Это С#. Все прекрасно компилируется. В чем проблема?


Мне казалось, что шарп не позволяет без дефолта свитчи делать. Мдя, очередное разочарование.

VD>>2. Что вызывается на пятой и последующих итерациях?


ВВ>Вызывается всегда один и тот же case 3. Выборка идет не по переменной цикла, а по переменной х.


А где гарантия, что код метода не заинлайнен, и что все свитч не выкинут к чертям?

ВВ>Хех, ты даже код внимательно не посмотрел.


Я вообще не люблю смотреть на сфероконей.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[16]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.09.10 15:37
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Замедление чего? Времени компляции компилятора? Времени компиляции самим компилятором? Компиляции чего? Самого компилятора?


Времени компиляции компилятором своих исходников. Т.е. если в буте бинарники со свитчами, то компиляция одного и того же кода проходит медленнее.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[15]: CIL switch и сопоставление с образцом
От: Аноним  
Дата: 14.09.10 15:42
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Воронков Василий, Вы писали:


ВВ>>На 99% реальных задач разницы во времени видно попросту не будет, что там свитч, что цепочка ифов.


VD>С целыми расклад несколько другой. Там нет проверок на null которые есть при переходе по вариантам имеющим умолчальное вхождение match-а. Там хардкейс выбрал константу — 5. Видимо тесты показали, что так оно эффективнее.


Нет. я взял это число с потолка.
Re[5]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.09.10 15:42
Оценка:
Здравствуйте, Аноним, Вы писали:

А>4 последовательных числа будут также последовательно сравниваться (ок, параметр можно поправить), 5 уже будут в switch превращаться.


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

И вообще, константу для целых и вариантов надо разделить (если это еще не сделано).

KK>>Не понимать. Я вижу два варианта с приемлемым потреблением памяти:

KK>>1. Цепочка ифов, т.е. линейный поиск (время O(n))
KK>>2. Бинарный поиск по множеству значений (время O(log n))

А>А я вижу в построении таблицы переходов (грубо и абстрактно):


Это... Это уже слова Воронкова. Ты меня с ним не путай.

А>index — индекс в таблице переходов.

А>br_size — длина инструкции BR с адресом:
А>
А>jump index * br_size //переходим на index * br_size байт вперед, попадая на одну из jump-кейзов
А>jump case0  // переход на код кейза 0
А>jump case1  // переход на код кейза 1 и т.д.
А>jump case2
А>jump case3
А>...
А>

А>З.Ы. могу заблуждаться в своих суждениях.

Думаю, что ты прав.

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


Это было бы круто, но наверно имеет смысл остановиться пока. А то пределов совершенству нет.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[12]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.09.10 15:47
Оценка:
Здравствуйте, Ka3a4oK, Вы писали:

KK>Не понимать. Я вижу два варианта с приемлемым потреблением памяти:

KK>1. Цепочка ифов, т.е. линейный поиск (время O(n))
KK>2. Бинарный поиск по множеству значений (время O(log n))

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

Скажем современные процессоры умеют предсказывать ветвление и осуществлять спекулятивные вычисления. Так найдя цепочку ифов (точнее их паттерн в инструкциях процессора) процессор может тупо распараллеливание их вычисления. Или еще что-то может повлиять (сбросы кэшей и т.п.). Так что единственный реальный критерий истины — это практика.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: CIL switch и сопоставление с образцом
От: Аноним  
Дата: 14.09.10 16:12
Оценка: 43 (1)
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Аноним, Вы писали:


А>>4 последовательных числа будут также последовательно сравниваться (ок, параметр можно поправить), 5 уже будут в switch превращаться.


VD>Хорошо бы провести отдельный тест с целыми. Потому как в одном я с Воронковым согласен — для негерированных ДКА свитчи могут оказаться предпочтительнее. Причем просто потому, что они более компактно в памяти представлены.


VD>И вообще, константу для целых и вариантов надо разделить (если это еще не сделано).


Константа для целых задается зесь (DecisionTreeCompiler.n line 422).
Константа для варинат — здесь (DecisionTreeCompiler.n line 367).
Re[5]: CIL switch и сопоставление с образцом
От: Ka3a4oK  
Дата: 14.09.10 18:05
Оценка:
А>А я вижу в построении таблицы переходов (грубо и абстрактно):

А>index — индекс в таблице переходов.

А>br_size — длина инструкции BR с адресом:
А>
А>jump index * br_size //переходим на index * br_size байт вперед, попадая на одну из jump-кейзов
А>jump case0  // переход на код кейза 0
А>jump case1  // переход на код кейза 1 и т.д.
А>jump case2
А>jump case3
А>...
А>

А>З.Ы. могу заблуждаться в своих суждениях.

Что собой представляет таблица переходов как структура данных? Как она строится и как в ней производится поиск?
Re[6]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.09.10 18:25
Оценка:
Здравствуйте, Ka3a4oK, Вы писали:

KK>Что собой представляет таблица переходов как структура данных? Как она строится и как в ней производится поиск?


Дык это надо дезасемблированный код смотреть. Мы же MSIL генерируем.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[7]: CIL switch и сопоставление с образцом
От: Ka3a4oK  
Дата: 14.09.10 18:54
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Ka3a4oK, Вы писали:


KK>>Что собой представляет таблица переходов как структура данных? Как она строится и как в ней производится поиск?


VD>Дык это надо дезасемблированный код смотреть. Мы же MSIL генерируем.


Ну тогда скорей всего там бинарный поиск и используется в общем случае. Т.е. говорить о константном времени выбора в худшем случае мы не можем.
Re[8]: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 14.09.10 19:21
Оценка:
Здравствуйте, Ka3a4oK, Вы писали:

KK>Здравствуйте, VladD2, Вы писали:


VD>>Здравствуйте, Ka3a4oK, Вы писали:


KK>>>Что собой представляет таблица переходов как структура данных? Как она строится и как в ней производится поиск?


VD>>Дык это надо дезасемблированный код смотреть. Мы же MSIL генерируем.


KK>Ну тогда скорей всего там бинарный поиск и используется в общем случае. Т.е. говорить о константном времени выбора в худшем случае мы не можем.


Вот это вряд ли. Пройди по ссылке на описание опкода switch в первом сообщении.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[8]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 14.09.10 19:29
Оценка:
Здравствуйте, Ka3a4oK, Вы писали:

VD>>Дык это надо дезасемблированный код смотреть. Мы же MSIL генерируем.


KK>Ну тогда скорей всего там бинарный поиск и используется в общем случае. Т.е. говорить о константном времени выбора в худшем случае мы не можем.


MSIL switch не работает с таблицами имеющими пропуски и генерирует (по видимому) тупой goto по адресу.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: CIL switch и сопоставление с образцом
От: Ka3a4oK  
Дата: 14.09.10 20:40
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Здравствуйте, Ka3a4oK, Вы писали:


VD>>>Дык это надо дезасемблированный код смотреть. Мы же MSIL генерируем.


KK>>Ну тогда скорей всего там бинарный поиск и используется в общем случае. Т.е. говорить о константном времени выбора в худшем случае мы не можем.


VD>MSIL switch не работает с таблицами имеющими пропуски и генерирует (по видимому) тупой goto по адресу.


Т.е. я правильно ли понимаю, что данное усовершенствование (применение инстуркции switch для патерн матчинга) будет работать только при патерн-матчинге интегральных типов, при этом множество выбора должно быть "без пропусков"?
Re[11]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 14.09.10 21:17
Оценка:
Здравствуйте, VladD2, Вы писали:

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

VD>Хардкейс же тебе сказал, что для целых ограничение другое.

Мне непонятно, зачем вообще нужно какое-то ограничение на кол-во вхождение в свитче.

ВВ>>Вызывается всегда один и тот же case 3. Выборка идет не по переменной цикла, а по переменной х.

VD>А где гарантия, что код метода не заинлайнен, и что все свитч не выкинут к чертям?

Какой метод? Методы со свитчами не инлайнятся.
Re[19]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 14.09.10 21:27
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Проверяй.


Вот тут за меня, оказывается, уже проверили:
http://stackoverflow.com/questions/44905/c-switch-statement-limitations-why#48060
Re[10]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 14.09.10 21:32
Оценка:
Здравствуйте, Ka3a4oK, Вы писали:

KK>Т.е. я правильно ли понимаю, что данное усовершенствование (применение инстуркции switch для патерн матчинга) будет работать только при патерн-матчинге интегральных типов, при этом множество выбора должно быть "без пропусков"?


Погугли как это сделано в Шарпе. Для строк используется люкап-таблица. Пропуски допустимы, но для свича вида { case 0; case 3; } будет сгенерирована таблица с четырьмя вхождениями, половина из которых — "холостые". Естественно, есть некий максимальный предел для пропусков, после которых джамп-таблица не генерируется, и компилятор переходит на другой алгоритм.
Re[11]: CIL switch и сопоставление с образцом
От: Ka3a4oK  
Дата: 14.09.10 23:05
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Здравствуйте, Ka3a4oK, Вы писали:


KK>>Т.е. я правильно ли понимаю, что данное усовершенствование (применение инстуркции switch для патерн матчинга) будет работать только при патерн-матчинге интегральных типов, при этом множество выбора должно быть "без пропусков"?


ВВ>Погугли как это сделано в Шарпе. Для строк используется люкап-таблица. Пропуски допустимы, но для свича вида { case 0; case 3; } будет сгенерирована таблица с четырьмя вхождениями, половина из которых — "холостые". Естественно, есть некий максимальный предел для пропусков, после которых джамп-таблица не генерируется, и компилятор переходит на другой алгоритм.


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

1. небольшие дыры -> таблица с константным временем
2. большие дыры -> бинарный поиск(или может даже хэш-таблица при большом количестве элементов)
Re[12]: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 15.09.10 06:08
Оценка:
Здравствуйте, Ka3a4oK, Вы писали:

KK>1. небольшие дыры -> таблица с константным временем

KK>2. большие дыры -> бинарный поиск(или может даже хэш-таблица при большом количестве элементов)


Что-то я сомневаюсь в том, что C# компилятор производит оптимизацию №2.
На каком количестве разреженных вхождений бинарный поиск будет в среднем быстрее линейного?
/* иЗвиНите зА неРовнЫй поЧерК */
Re[17]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 15.09.10 07:18
Оценка:
Здравствуйте, VladD2, Вы писали:

ВВ>>Замедление чего? Времени компляции компилятора? Времени компиляции самим компилятором? Компиляции чего? Самого компилятора?

VD>Времени компиляции компилятором своих исходников. Т.е. если в буте бинарники со свитчами, то компиляция одного и того же кода проходит медленнее.

Кстати, здесь может играть роль тот фактор, что ДЖИТ не инлайнит методы, в которых есть оп-код Switch. Ну и само собой для небольших кейсов Switch может попортить работу предсказателю. Наконец у вас есть дополнительных cost для свитчей по вариантам — проверка на нуль (ты сам говорил) и вызов виртуального метода, который возвращает код вхождения (?). Для целых эти накладные расходы отсутствуют.

Как обычно я забыл, что в Немерле *все* условные конструции — это матч. И сие, конечно, вносит свои коррективы.
Тут возможно два варианта:

1. Ввести опцию компилятора forceSwitch, при которой джамп-таблица генерируется для любого кол-ва вхождений
2. Добавить специальное ключевое слово, атрибут, whatever с теми же целями.

Чем не нравится вариант с ограничением:

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

Кстати, пропуски при построении свитча по целым учитываются?
Re: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 15.09.10 07:32
Оценка: 111 (1)
Здравствуйте, hardcase, Вы писали:


Для управления оптимизирующего алгоритма в компиляторе появились два дополнительных параметра: -min-switch-size-variants (-Oswv) и -min-switch-size-ordinals (-Oswo).

Также в MSBuild-тасках теперь есть возможность указывать параметры командной строки с помощью тега <CustomArguments>,
например:
<CustomArguments>
-Oswv:15 -Oswo:3
</CustomArguments>
/* иЗвиНите зА неРовнЫй поЧерК */
Re[18]: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 15.09.10 07:36
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>1. Ввести опцию компилятора forceSwitch, при которой джамп-таблица генерируется для любого кол-ва вхождений

ВВ>2. Добавить специальное ключевое слово, атрибут, whatever с теми же целями.

Я повторюсь, но это несколько бессмысленно для матчинга по вариантам... Ну не дает оно прироста на 10 вхождениях.

ВВ>Чем не нравится вариант с ограничением:


ВВ>Кстати, пропуски при построении свитча по целым учитываются?


Алгоритм закрывает до двух пропусков в матче, как по числам так и по вариантам.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[19]: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 15.09.10 07:39
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Алгоритм закрывает до двух пропусков в матче, как по числам так и по вариантам.


Поясню, для матча
match(x)
{
 | 0 =>  ...
 | 3 =>  ...
 | 6 =>  ...
 | 7 =>  ...
 | 8 =>  ...
 | 11 => ...
 | _ =>  ...
}

будет сгенерирован единственный switch.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[13]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 15.09.10 07:52
Оценка: 12 (1)
Здравствуйте, hardcase, Вы писали:

H>Здравствуйте, Ka3a4oK, Вы писали:


KK>>1. небольшие дыры -> таблица с константным временем

KK>>2. большие дыры -> бинарный поиск(или может даже хэш-таблица при большом количестве элементов)


H>Что-то я сомневаюсь в том, что C# компилятор производит оптимизацию №2.

H>На каком количестве разреженных вхождений бинарный поиск будет в среднем быстрее линейного?


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            var x = 5;

            switch (x)
            {
                case 0: x += 1; break;
                case 5: x += 1; break;
                case 100: x += 1; break;
                case 200: x += 1; break;
                case 300: x += 1; break;
                case 400: x += 1; break;
                case 500: x += 1; break;
                case 600: x += 1; break;
                case 700: x += 1; break;
                case 800: x += 1; break;
                case 900: x += 1; break;
                case 1000: x += 1; break;
                case 1100: x += 1; break;
                case 1200: x += 1; break;
                case 1300: x += 1; break;
                case 1400: x += 1; break;
                case 1500: x += 1; break;
                case 1600: x += 1; break;

                case 1700: x += 1; break;
                case 1800: x += 1; break;
                case 1900: x += 1; break;
                case 2000: x += 1; break;

                case 2100: x += 1; break;
                case 2200: x += 1; break;
                case 2300: x += 1; break;

                case 2400: x += 1; break;
                case 2500: x += 1; break;
                case 2600: x += 1; break;
                case 2700: x += 1; break;
                case 2800: x += 1; break;
                case 2900: x += 1; break;
                case 3000: x += 1; break;
                case 3100: x += 1; break;

                case 3200: x += 1; break;
                case 3300: x += 1; break;
                case 3400: x += 1; break;
                case 3500: x += 1; break;
                case 3600: x += 1; break;
                case 3700: x += 1; break;
                case 3800: x += 1; break;
                case 3900: x += 1; break;
                case 4000: x += 1; break;
                case 4100: x += 1; break;

                case 4200: x += 1; break;
                case 4300: x += 1; break;
                case 4400: x += 1; break;
                case 4500: x += 1; break;
                case 4600: x += 1; break;
                case 4700: x += 1; break;
                case 4800: x += 1; break;
                case 4900: x += 1; break;

                case 5000: x += 1; break;
                case 5100: x += 1; break;
                case 5200: x += 1; break;
                case 5300: x += 1; break;
                case 5400: x += 1; break;
                case 5500: x += 1; break;
                case 5600: x += 1; break;
                case 5700: x += 1; break;
                case 5800: x += 1; break;
                case 5900: x += 1; break;
                case 6000: x += 1; break;
                case 6100: x += 1; break;

                case 6200: x += 1; break;
                case 6300: x += 1; break;
                case 6400: x += 1; break;
                case 6500: x += 1; break;
                case 6600: x += 1; break;
                case 6700: x += 1; break;
                case 6800: x += 1; break;
                case 6900: x += 1; break;
                case 7000: x += 1; break;
                case 7100: x += 1; break;

                case 7200: x += 1; break;
                case 7300: x += 1; break;
                case 7400: x += 1; break;
                case 7500: x += 1; break;
                case 7600: x += 1; break;
                case 7700: x += 1; break;
                case 7800: x += 1; break;
                case 7900: x += 1; break;
                case 8000: x += 1; break;
                case 8100: x += 1; break;

                case 8200: x += 1; break;
                case 8300: x += 1; break;
                case 8400: x += 1; break;
                case 8500: x += 1; break;
                case 8600: x += 1; break;
                case 8700: x += 1; break;
                case 8800: x += 1; break;
                case 8900: x += 1; break;

                case 9000: x += 1; break;
                case 9100: x += 1; break;
                case 9200: x += 1; break;
                case 9300: x += 1; break;
                case 9400: x += 1; break;
                case 9500: x += 1; break;
                case 9600: x += 1; break;
                case 9700: x += 1; break;
                case 9800: x += 1; break;
                case 9900: x += 1; break;
                case 10000: x += 1; break;

            }
        }
    }
}




.method private hidebysig static void Main(string[] args) cil managed
{
    .entrypoint
    .maxstack 2
    .locals init (
        [0] int32 x,
        [1] int32 CS$0$0000)
    L_0000: ldc.i4.5 
    L_0001: stloc.0 
    L_0002: ldloc.0 
    L_0003: stloc.1 
    L_0004: ldloc.1 
    L_0005: ldc.i4 0x1324
    L_000a: bgt L_02de
    L_000f: ldloc.1 
    L_0010: ldc.i4 0x8fc
    L_0015: bgt L_016b
    L_001a: ldloc.1 
    L_001b: ldc.i4 0x3e8
    L_0020: bgt L_00b7
    L_0025: ldloc.1 
    L_0026: ldc.i4 400
    L_002b: bgt.s L_006b
    L_002d: ldloc.1 
    L_002e: ldc.i4.s 100
    L_0030: bgt.s L_0049
    L_0032: ldloc.1 
    L_0033: ldc.i4.0 
    L_0034: beq L_05bb
    L_0039: ldloc.1 
    L_003a: ldc.i4.5 
    L_003b: beq L_05c0
    L_0040: ldloc.1 
    L_0041: ldc.i4.s 100
    L_0043: beq L_05c5
    L_0048: ret 
    L_0049: ldloc.1 
    L_004a: ldc.i4 200
    L_004f: beq L_05ca
    L_0054: ldloc.1 
    L_0055: ldc.i4 300
    L_005a: beq L_05cf
    L_005f: ldloc.1 
    L_0060: ldc.i4 400
    L_0065: beq L_05d4
    L_006a: ret 
    L_006b: ldloc.1 
    L_006c: ldc.i4 700
    L_0071: bgt.s L_0095
    L_0073: ldloc.1 
    L_0074: ldc.i4 500
    L_0079: beq L_05d9
    L_007e: ldloc.1 
    L_007f: ldc.i4 600
    L_0084: beq L_05de
    L_0089: ldloc.1 
    L_008a: ldc.i4 700
    L_008f: beq L_05e3
    L_0094: ret 
    L_0095: ldloc.1 
    L_0096: ldc.i4 800
    L_009b: beq L_05e8
    L_00a0: ldloc.1 
    L_00a1: ldc.i4 900
    L_00a6: beq L_05ed
    L_00ab: ldloc.1 
    L_00ac: ldc.i4 0x3e8
    L_00b1: beq L_05f2
    L_00b6: ret 
    L_00b7: ldloc.1 
    L_00b8: ldc.i4 0x640
    L_00bd: bgt.s L_010b
    L_00bf: ldloc.1 
    L_00c0: ldc.i4 0x514
    L_00c5: bgt.s L_00e9
    L_00c7: ldloc.1 
    L_00c8: ldc.i4 0x44c
    L_00cd: beq L_05f7
    L_00d2: ldloc.1 
    L_00d3: ldc.i4 0x4b0
    L_00d8: beq L_05fc
    L_00dd: ldloc.1 
    L_00de: ldc.i4 0x514
    L_00e3: beq L_0601
    L_00e8: ret 
    L_00e9: ldloc.1 
    L_00ea: ldc.i4 0x578
    L_00ef: beq L_0606
    L_00f4: ldloc.1 
    L_00f5: ldc.i4 0x5dc
    L_00fa: beq L_060b
    L_00ff: ldloc.1 
    L_0100: ldc.i4 0x640
    L_0105: beq L_0610
    L_010a: ret 
    L_010b: ldloc.1 
    L_010c: ldc.i4 0x76c
    L_0111: bgt.s L_0135
    L_0113: ldloc.1 
    L_0114: ldc.i4 0x6a4
    L_0119: beq L_0615
    L_011e: ldloc.1 
    L_011f: ldc.i4 0x708
    L_0124: beq L_061a
    L_0129: ldloc.1 
    L_012a: ldc.i4 0x76c
    L_012f: beq L_061f
    L_0134: ret 
    L_0135: ldloc.1 
    L_0136: ldc.i4 0x834
    L_013b: bgt.s L_0154
    L_013d: ldloc.1 
    L_013e: ldc.i4 0x7d0
    L_0143: beq L_0624
    L_0148: ldloc.1 
    L_0149: ldc.i4 0x834
    L_014e: beq L_0629
    L_0153: ret 
    L_0154: ldloc.1 
    L_0155: ldc.i4 0x898
    L_015a: beq L_062e
    L_015f: ldloc.1 
    L_0160: ldc.i4 0x8fc
    L_0165: beq L_0633
    L_016a: ret 
    L_016b: ldloc.1 
    L_016c: ldc.i4 0xe10
    L_0171: bgt L_022a
    L_0176: ldloc.1 
    L_0177: ldc.i4 0xb54
    L_017c: bgt.s L_01ca
    L_017e: ldloc.1 
    L_017f: ldc.i4 0xa28
    L_0184: bgt.s L_01a8
    L_0186: ldloc.1 
    L_0187: ldc.i4 0x960
    L_018c: beq L_0638
    L_0191: ldloc.1 
    L_0192: ldc.i4 0x9c4
    L_0197: beq L_063d
    L_019c: ldloc.1 
    L_019d: ldc.i4 0xa28
    L_01a2: beq L_0642
    L_01a7: ret 
    L_01a8: ldloc.1 
    L_01a9: ldc.i4 0xa8c
    L_01ae: beq L_0647
    L_01b3: ldloc.1 
    L_01b4: ldc.i4 0xaf0
    L_01b9: beq L_064c
    L_01be: ldloc.1 
    L_01bf: ldc.i4 0xb54
    L_01c4: beq L_0651
    L_01c9: ret 
    L_01ca: ldloc.1 
    L_01cb: ldc.i4 0xc80
    L_01d0: bgt.s L_01f4
    L_01d2: ldloc.1 
    L_01d3: ldc.i4 0xbb8
    L_01d8: beq L_0656
    L_01dd: ldloc.1 
    L_01de: ldc.i4 0xc1c
    L_01e3: beq L_065b
    L_01e8: ldloc.1 
    L_01e9: ldc.i4 0xc80
    L_01ee: beq L_0660
    L_01f3: ret 
    L_01f4: ldloc.1 
    L_01f5: ldc.i4 0xd48
    L_01fa: bgt.s L_0213
    L_01fc: ldloc.1 
    L_01fd: ldc.i4 0xce4
    L_0202: beq L_0665
    L_0207: ldloc.1 
    L_0208: ldc.i4 0xd48
    L_020d: beq L_066a
    L_0212: ret 
    L_0213: ldloc.1 
    L_0214: ldc.i4 0xdac
    L_0219: beq L_066f
    L_021e: ldloc.1 
    L_021f: ldc.i4 0xe10
    L_0224: beq L_0674
    L_0229: ret 
    L_022a: ldloc.1 
    L_022b: ldc.i4 0x1068
    L_0230: bgt.s L_027e
    L_0232: ldloc.1 
    L_0233: ldc.i4 0xf3c
    L_0238: bgt.s L_025c
    L_023a: ldloc.1 
    L_023b: ldc.i4 0xe74
    L_0240: beq L_0679
    L_0245: ldloc.1 
    L_0246: ldc.i4 0xed8
    L_024b: beq L_067e
    L_0250: ldloc.1 
    L_0251: ldc.i4 0xf3c
    L_0256: beq L_0683
    L_025b: ret 
    L_025c: ldloc.1 
    L_025d: ldc.i4 0xfa0
    L_0262: beq L_0688
    L_0267: ldloc.1 
    L_0268: ldc.i4 0x1004
    L_026d: beq L_068d
    L_0272: ldloc.1 
    L_0273: ldc.i4 0x1068
    L_0278: beq L_0692
    L_027d: ret 
    L_027e: ldloc.1 
    L_027f: ldc.i4 0x1194
    L_0284: bgt.s L_02a8
    L_0286: ldloc.1 
    L_0287: ldc.i4 0x10cc
    L_028c: beq L_0697
    L_0291: ldloc.1 
    L_0292: ldc.i4 0x1130
    L_0297: beq L_069c
    L_029c: ldloc.1 
    L_029d: ldc.i4 0x1194
    L_02a2: beq L_06a1
    L_02a7: ret 
    L_02a8: ldloc.1 
    L_02a9: ldc.i4 0x125c
    L_02ae: bgt.s L_02c7
    L_02b0: ldloc.1 
    L_02b1: ldc.i4 0x11f8
    L_02b6: beq L_06a6
    L_02bb: ldloc.1 
    L_02bc: ldc.i4 0x125c
    L_02c1: beq L_06ab
    L_02c6: ret 
    L_02c7: ldloc.1 
    L_02c8: ldc.i4 0x12c0
    L_02cd: beq L_06b0
    L_02d2: ldloc.1 
    L_02d3: ldc.i4 0x1324
    L_02d8: beq L_06b5
    L_02dd: ret 
    L_02de: ldloc.1 
    L_02df: ldc.i4 0x1ce8
    L_02e4: bgt L_0448
    L_02e9: ldloc.1 
    L_02ea: ldc.i4 0x17d4
    L_02ef: bgt L_0394
    L_02f4: ldloc.1 
    L_02f5: ldc.i4 0x157c
    L_02fa: bgt.s L_0348
    L_02fc: ldloc.1 
    L_02fd: ldc.i4 0x1450
    L_0302: bgt.s L_0326
    L_0304: ldloc.1 
    L_0305: ldc.i4 0x1388
    L_030a: beq L_06ba
    L_030f: ldloc.1 
    L_0310: ldc.i4 0x13ec
    L_0315: beq L_06bf
    L_031a: ldloc.1 
    L_031b: ldc.i4 0x1450
    L_0320: beq L_06c4
    L_0325: ret 
    L_0326: ldloc.1 
    L_0327: ldc.i4 0x14b4
    L_032c: beq L_06c9
    L_0331: ldloc.1 
    L_0332: ldc.i4 0x1518
    L_0337: beq L_06ce
    L_033c: ldloc.1 
    L_033d: ldc.i4 0x157c
    L_0342: beq L_06d3
    L_0347: ret 
    L_0348: ldloc.1 
    L_0349: ldc.i4 0x16a8
    L_034e: bgt.s L_0372
    L_0350: ldloc.1 
    L_0351: ldc.i4 0x15e0
    L_0356: beq L_06d8
    L_035b: ldloc.1 
    L_035c: ldc.i4 0x1644
    L_0361: beq L_06dd
    L_0366: ldloc.1 
    L_0367: ldc.i4 0x16a8
    L_036c: beq L_06e2
    L_0371: ret 
    L_0372: ldloc.1 
    L_0373: ldc.i4 0x170c
    L_0378: beq L_06e7
    L_037d: ldloc.1 
    L_037e: ldc.i4 0x1770
    L_0383: beq L_06ec
    L_0388: ldloc.1 
    L_0389: ldc.i4 0x17d4
    L_038e: beq L_06f1
    L_0393: ret 
    L_0394: ldloc.1 
    L_0395: ldc.i4 0x1a2c
    L_039a: bgt.s L_03e8
    L_039c: ldloc.1 
    L_039d: ldc.i4 0x1900
    L_03a2: bgt.s L_03c6
    L_03a4: ldloc.1 
    L_03a5: ldc.i4 0x1838
    L_03aa: beq L_06f6
    L_03af: ldloc.1 
    L_03b0: ldc.i4 0x189c
    L_03b5: beq L_06fb
    L_03ba: ldloc.1 
    L_03bb: ldc.i4 0x1900
    L_03c0: beq L_0700
    L_03c5: ret 
    L_03c6: ldloc.1 
    L_03c7: ldc.i4 0x1964
    L_03cc: beq L_0705
    L_03d1: ldloc.1 
    L_03d2: ldc.i4 0x19c8
    L_03d7: beq L_070a
    L_03dc: ldloc.1 
    L_03dd: ldc.i4 0x1a2c
    L_03e2: beq L_070f
    L_03e7: ret 
    L_03e8: ldloc.1 
    L_03e9: ldc.i4 0x1b58
    L_03ee: bgt.s L_0412
    L_03f0: ldloc.1 
    L_03f1: ldc.i4 0x1a90
    L_03f6: beq L_0714
    L_03fb: ldloc.1 
    L_03fc: ldc.i4 0x1af4
    L_0401: beq L_0719
    L_0406: ldloc.1 
    L_0407: ldc.i4 0x1b58
    L_040c: beq L_071e
    L_0411: ret 
    L_0412: ldloc.1 
    L_0413: ldc.i4 0x1c20
    L_0418: bgt.s L_0431
    L_041a: ldloc.1 
    L_041b: ldc.i4 0x1bbc
    L_0420: beq L_0723
    L_0425: ldloc.1 
    L_0426: ldc.i4 0x1c20
    L_042b: beq L_0728
    L_0430: ret 
    L_0431: ldloc.1 
    L_0432: ldc.i4 0x1c84
    L_0437: beq L_072d
    L_043c: ldloc.1 
    L_043d: ldc.i4 0x1ce8
    L_0442: beq L_0732
    L_0447: ret 
    L_0448: ldloc.1 
    L_0449: ldc.i4 0x21fc
    L_044e: bgt L_0507
    L_0453: ldloc.1 
    L_0454: ldc.i4 0x1f40
    L_0459: bgt.s L_04a7
    L_045b: ldloc.1 
    L_045c: ldc.i4 0x1e14
    L_0461: bgt.s L_0485
    L_0463: ldloc.1 
    L_0464: ldc.i4 0x1d4c
    L_0469: beq L_0737
    L_046e: ldloc.1 
    L_046f: ldc.i4 0x1db0
    L_0474: beq L_073c
    L_0479: ldloc.1 
    L_047a: ldc.i4 0x1e14
    L_047f: beq L_0741
    L_0484: ret 
    L_0485: ldloc.1 
    L_0486: ldc.i4 0x1e78
    L_048b: beq L_0746
    L_0490: ldloc.1 
    L_0491: ldc.i4 0x1edc
    L_0496: beq L_074b
    L_049b: ldloc.1 
    L_049c: ldc.i4 0x1f40
    L_04a1: beq L_0750
    L_04a6: ret 
    L_04a7: ldloc.1 
    L_04a8: ldc.i4 0x206c
    L_04ad: bgt.s L_04d1
    L_04af: ldloc.1 
    L_04b0: ldc.i4 0x1fa4
    L_04b5: beq L_0755
    L_04ba: ldloc.1 
    L_04bb: ldc.i4 0x2008
    L_04c0: beq L_075a
    L_04c5: ldloc.1 
    L_04c6: ldc.i4 0x206c
    L_04cb: beq L_075f
    L_04d0: ret 
    L_04d1: ldloc.1 
    L_04d2: ldc.i4 0x2134
    L_04d7: bgt.s L_04f0
    L_04d9: ldloc.1 
    L_04da: ldc.i4 0x20d0
    L_04df: beq L_0764
    L_04e4: ldloc.1 
    L_04e5: ldc.i4 0x2134
    L_04ea: beq L_0769
    L_04ef: ret 
    L_04f0: ldloc.1 
    L_04f1: ldc.i4 0x2198
    L_04f6: beq L_076e
    L_04fb: ldloc.1 
    L_04fc: ldc.i4 0x21fc
    L_0501: beq L_0773
    L_0506: ret 
    L_0507: ldloc.1 
    L_0508: ldc.i4 0x2454
    L_050d: bgt.s L_055b
    L_050f: ldloc.1 
    L_0510: ldc.i4 0x2328
    L_0515: bgt.s L_0539
    L_0517: ldloc.1 
    L_0518: ldc.i4 0x2260
    L_051d: beq L_0778
    L_0522: ldloc.1 
    L_0523: ldc.i4 0x22c4
    L_0528: beq L_077d
    L_052d: ldloc.1 
    L_052e: ldc.i4 0x2328
    L_0533: beq L_0782
    L_0538: ret 
    L_0539: ldloc.1 
    L_053a: ldc.i4 0x238c
    L_053f: beq L_0787
    L_0544: ldloc.1 
    L_0545: ldc.i4 0x23f0
    L_054a: beq L_078c
    L_054f: ldloc.1 
    L_0550: ldc.i4 0x2454
    L_0555: beq L_0791
    L_055a: ret 
    L_055b: ldloc.1 
    L_055c: ldc.i4 0x2580
    L_0561: bgt.s L_0585
    L_0563: ldloc.1 
    L_0564: ldc.i4 0x24b8
    L_0569: beq L_0796
    L_056e: ldloc.1 
    L_056f: ldc.i4 0x251c
    L_0574: beq L_079b
    L_0579: ldloc.1 
    L_057a: ldc.i4 0x2580
    L_057f: beq L_07a0
    L_0584: ret 
    L_0585: ldloc.1 
    L_0586: ldc.i4 0x2648
    L_058b: bgt.s L_05a4
    L_058d: ldloc.1 
    L_058e: ldc.i4 0x25e4
    L_0593: beq L_07a5
    L_0598: ldloc.1 
    L_0599: ldc.i4 0x2648
    L_059e: beq L_07aa
    L_05a3: ret 
    L_05a4: ldloc.1 
    L_05a5: ldc.i4 0x26ac
    L_05aa: beq L_07af
    L_05af: ldloc.1 
    L_05b0: ldc.i4 0x2710
    L_05b5: beq L_07b4
    L_05ba: ret 
    L_05bb: ldloc.0 
    L_05bc: ldc.i4.1 
    L_05bd: add 
    L_05be: stloc.0 
    L_05bf: ret 
    L_05c0: ldloc.0 
    L_05c1: ldc.i4.1 
    L_05c2: add 
    L_05c3: stloc.0 
    L_05c4: ret 
    L_05c5: ldloc.0 
    L_05c6: ldc.i4.1 
    L_05c7: add 
    L_05c8: stloc.0 
    L_05c9: ret 
    L_05ca: ldloc.0 
    L_05cb: ldc.i4.1 
    L_05cc: add 
    L_05cd: stloc.0 
    L_05ce: ret 
    L_05cf: ldloc.0 
    L_05d0: ldc.i4.1 
    L_05d1: add 
    L_05d2: stloc.0 
    L_05d3: ret 
    L_05d4: ldloc.0 
    L_05d5: ldc.i4.1 
    L_05d6: add 
    L_05d7: stloc.0 
    L_05d8: ret 
    L_05d9: ldloc.0 
    L_05da: ldc.i4.1 
    L_05db: add 
    L_05dc: stloc.0 
    L_05dd: ret 
    L_05de: ldloc.0 
    L_05df: ldc.i4.1 
    L_05e0: add 
    L_05e1: stloc.0 
    L_05e2: ret 
    L_05e3: ldloc.0 
    L_05e4: ldc.i4.1 
    L_05e5: add 
    L_05e6: stloc.0 
    L_05e7: ret 
    L_05e8: ldloc.0 
    L_05e9: ldc.i4.1 
    L_05ea: add 
    L_05eb: stloc.0 
    L_05ec: ret 
    L_05ed: ldloc.0 
    L_05ee: ldc.i4.1 
    L_05ef: add 
    L_05f0: stloc.0 
    L_05f1: ret 
    L_05f2: ldloc.0 
    L_05f3: ldc.i4.1 
    L_05f4: add 
    L_05f5: stloc.0 
    L_05f6: ret 
    L_05f7: ldloc.0 
    L_05f8: ldc.i4.1 
    L_05f9: add 
    L_05fa: stloc.0 
    L_05fb: ret 
    L_05fc: ldloc.0 
    L_05fd: ldc.i4.1 
    L_05fe: add 
    L_05ff: stloc.0 
    L_0600: ret 
    L_0601: ldloc.0 
    L_0602: ldc.i4.1 
    L_0603: add 
    L_0604: stloc.0 
    L_0605: ret 
    L_0606: ldloc.0 
    L_0607: ldc.i4.1 
    L_0608: add 
    L_0609: stloc.0 
    L_060a: ret 
    L_060b: ldloc.0 
    L_060c: ldc.i4.1 
    L_060d: add 
    L_060e: stloc.0 
    L_060f: ret 
    L_0610: ldloc.0 
    L_0611: ldc.i4.1 
    L_0612: add 
    L_0613: stloc.0 
    L_0614: ret 
    L_0615: ldloc.0 
    L_0616: ldc.i4.1 
    L_0617: add 
    L_0618: stloc.0 
    L_0619: ret 
    L_061a: ldloc.0 
    L_061b: ldc.i4.1 
    L_061c: add 
    L_061d: stloc.0 
    L_061e: ret 
    L_061f: ldloc.0 
    L_0620: ldc.i4.1 
    L_0621: add 
    L_0622: stloc.0 
    L_0623: ret 
    L_0624: ldloc.0 
    L_0625: ldc.i4.1 
    L_0626: add 
    L_0627: stloc.0 
    L_0628: ret 
    L_0629: ldloc.0 
    L_062a: ldc.i4.1 
    L_062b: add 
    L_062c: stloc.0 
    L_062d: ret 
    L_062e: ldloc.0 
    L_062f: ldc.i4.1 
    L_0630: add 
    L_0631: stloc.0 
    L_0632: ret 
    L_0633: ldloc.0 
    L_0634: ldc.i4.1 
    L_0635: add 
    L_0636: stloc.0 
    L_0637: ret 
    L_0638: ldloc.0 
    L_0639: ldc.i4.1 
    L_063a: add 
    L_063b: stloc.0 
    L_063c: ret 
    L_063d: ldloc.0 
    L_063e: ldc.i4.1 
    L_063f: add 
    L_0640: stloc.0 
    L_0641: ret 
    L_0642: ldloc.0 
    L_0643: ldc.i4.1 
    L_0644: add 
    L_0645: stloc.0 
    L_0646: ret 
    L_0647: ldloc.0 
    L_0648: ldc.i4.1 
    L_0649: add 
    L_064a: stloc.0 
    L_064b: ret 
    L_064c: ldloc.0 
    L_064d: ldc.i4.1 
    L_064e: add 
    L_064f: stloc.0 
    L_0650: ret 
    L_0651: ldloc.0 
    L_0652: ldc.i4.1 
    L_0653: add 
    L_0654: stloc.0 
    L_0655: ret 
    L_0656: ldloc.0 
    L_0657: ldc.i4.1 
    L_0658: add 
    L_0659: stloc.0 
    L_065a: ret 
    L_065b: ldloc.0 
    L_065c: ldc.i4.1 
    L_065d: add 
    L_065e: stloc.0 
    L_065f: ret 
    L_0660: ldloc.0 
    L_0661: ldc.i4.1 
    L_0662: add 
    L_0663: stloc.0 
    L_0664: ret 
    L_0665: ldloc.0 
    L_0666: ldc.i4.1 
    L_0667: add 
    L_0668: stloc.0 
    L_0669: ret 
    L_066a: ldloc.0 
    L_066b: ldc.i4.1 
    L_066c: add 
    L_066d: stloc.0 
    L_066e: ret 
    L_066f: ldloc.0 
    L_0670: ldc.i4.1 
    L_0671: add 
    L_0672: stloc.0 
    L_0673: ret 
    L_0674: ldloc.0 
    L_0675: ldc.i4.1 
    L_0676: add 
    L_0677: stloc.0 
    L_0678: ret 
    L_0679: ldloc.0 
    L_067a: ldc.i4.1 
    L_067b: add 
    L_067c: stloc.0 
    L_067d: ret 
    L_067e: ldloc.0 
    L_067f: ldc.i4.1 
    L_0680: add 
    L_0681: stloc.0 
    L_0682: ret 
    L_0683: ldloc.0 
    L_0684: ldc.i4.1 
    L_0685: add 
    L_0686: stloc.0 
    L_0687: ret 
    L_0688: ldloc.0 
    L_0689: ldc.i4.1 
    L_068a: add 
    L_068b: stloc.0 
    L_068c: ret 
    L_068d: ldloc.0 
    L_068e: ldc.i4.1 
    L_068f: add 
    L_0690: stloc.0 
    L_0691: ret 
    L_0692: ldloc.0 
    L_0693: ldc.i4.1 
    L_0694: add 
    L_0695: stloc.0 
    L_0696: ret 
    L_0697: ldloc.0 
    L_0698: ldc.i4.1 
    L_0699: add 
    L_069a: stloc.0 
    L_069b: ret 
    L_069c: ldloc.0 
    L_069d: ldc.i4.1 
    L_069e: add 
    L_069f: stloc.0 
    L_06a0: ret 
    L_06a1: ldloc.0 
    L_06a2: ldc.i4.1 
    L_06a3: add 
    L_06a4: stloc.0 
    L_06a5: ret 
    L_06a6: ldloc.0 
    L_06a7: ldc.i4.1 
    L_06a8: add 
    L_06a9: stloc.0 
    L_06aa: ret 
    L_06ab: ldloc.0 
    L_06ac: ldc.i4.1 
    L_06ad: add 
    L_06ae: stloc.0 
    L_06af: ret 
    L_06b0: ldloc.0 
    L_06b1: ldc.i4.1 
    L_06b2: add 
    L_06b3: stloc.0 
    L_06b4: ret 
    L_06b5: ldloc.0 
    L_06b6: ldc.i4.1 
    L_06b7: add 
    L_06b8: stloc.0 
    L_06b9: ret 
    L_06ba: ldloc.0 
    L_06bb: ldc.i4.1 
    L_06bc: add 
    L_06bd: stloc.0 
    L_06be: ret 
    L_06bf: ldloc.0 
    L_06c0: ldc.i4.1 
    L_06c1: add 
    L_06c2: stloc.0 
    L_06c3: ret 
    L_06c4: ldloc.0 
    L_06c5: ldc.i4.1 
    L_06c6: add 
    L_06c7: stloc.0 
    L_06c8: ret 
    L_06c9: ldloc.0 
    L_06ca: ldc.i4.1 
    L_06cb: add 
    L_06cc: stloc.0 
    L_06cd: ret 
    L_06ce: ldloc.0 
    L_06cf: ldc.i4.1 
    L_06d0: add 
    L_06d1: stloc.0 
    L_06d2: ret 
    L_06d3: ldloc.0 
    L_06d4: ldc.i4.1 
    L_06d5: add 
    L_06d6: stloc.0 
    L_06d7: ret 
    L_06d8: ldloc.0 
    L_06d9: ldc.i4.1 
    L_06da: add 
    L_06db: stloc.0 
    L_06dc: ret 
    L_06dd: ldloc.0 
    L_06de: ldc.i4.1 
    L_06df: add 
    L_06e0: stloc.0 
    L_06e1: ret 
    L_06e2: ldloc.0 
    L_06e3: ldc.i4.1 
    L_06e4: add 
    L_06e5: stloc.0 
    L_06e6: ret 
    L_06e7: ldloc.0 
    L_06e8: ldc.i4.1 
    L_06e9: add 
    L_06ea: stloc.0 
    L_06eb: ret 
    L_06ec: ldloc.0 
    L_06ed: ldc.i4.1 
    L_06ee: add 
    L_06ef: stloc.0 
    L_06f0: ret 
    L_06f1: ldloc.0 
    L_06f2: ldc.i4.1 
    L_06f3: add 
    L_06f4: stloc.0 
    L_06f5: ret 
    L_06f6: ldloc.0 
    L_06f7: ldc.i4.1 
    L_06f8: add 
    L_06f9: stloc.0 
    L_06fa: ret 
    L_06fb: ldloc.0 
    L_06fc: ldc.i4.1 
    L_06fd: add 
    L_06fe: stloc.0 
    L_06ff: ret 
    L_0700: ldloc.0 
    L_0701: ldc.i4.1 
    L_0702: add 
    L_0703: stloc.0 
    L_0704: ret 
    L_0705: ldloc.0 
    L_0706: ldc.i4.1 
    L_0707: add 
    L_0708: stloc.0 
    L_0709: ret 
    L_070a: ldloc.0 
    L_070b: ldc.i4.1 
    L_070c: add 
    L_070d: stloc.0 
    L_070e: ret 
    L_070f: ldloc.0 
    L_0710: ldc.i4.1 
    L_0711: add 
    L_0712: stloc.0 
    L_0713: ret 
    L_0714: ldloc.0 
    L_0715: ldc.i4.1 
    L_0716: add 
    L_0717: stloc.0 
    L_0718: ret 
    L_0719: ldloc.0 
    L_071a: ldc.i4.1 
    L_071b: add 
    L_071c: stloc.0 
    L_071d: ret 
    L_071e: ldloc.0 
    L_071f: ldc.i4.1 
    L_0720: add 
    L_0721: stloc.0 
    L_0722: ret 
    L_0723: ldloc.0 
    L_0724: ldc.i4.1 
    L_0725: add 
    L_0726: stloc.0 
    L_0727: ret 
    L_0728: ldloc.0 
    L_0729: ldc.i4.1 
    L_072a: add 
    L_072b: stloc.0 
    L_072c: ret 
    L_072d: ldloc.0 
    L_072e: ldc.i4.1 
    L_072f: add 
    L_0730: stloc.0 
    L_0731: ret 
    L_0732: ldloc.0 
    L_0733: ldc.i4.1 
    L_0734: add 
    L_0735: stloc.0 
    L_0736: ret 
    L_0737: ldloc.0 
    L_0738: ldc.i4.1 
    L_0739: add 
    L_073a: stloc.0 
    L_073b: ret 
    L_073c: ldloc.0 
    L_073d: ldc.i4.1 
    L_073e: add 
    L_073f: stloc.0 
    L_0740: ret 
    L_0741: ldloc.0 
    L_0742: ldc.i4.1 
    L_0743: add 
    L_0744: stloc.0 
    L_0745: ret 
    L_0746: ldloc.0 
    L_0747: ldc.i4.1 
    L_0748: add 
    L_0749: stloc.0 
    L_074a: ret 
    L_074b: ldloc.0 
    L_074c: ldc.i4.1 
    L_074d: add 
    L_074e: stloc.0 
    L_074f: ret 
    L_0750: ldloc.0 
    L_0751: ldc.i4.1 
    L_0752: add 
    L_0753: stloc.0 
    L_0754: ret 
    L_0755: ldloc.0 
    L_0756: ldc.i4.1 
    L_0757: add 
    L_0758: stloc.0 
    L_0759: ret 
    L_075a: ldloc.0 
    L_075b: ldc.i4.1 
    L_075c: add 
    L_075d: stloc.0 
    L_075e: ret 
    L_075f: ldloc.0 
    L_0760: ldc.i4.1 
    L_0761: add 
    L_0762: stloc.0 
    L_0763: ret 
    L_0764: ldloc.0 
    L_0765: ldc.i4.1 
    L_0766: add 
    L_0767: stloc.0 
    L_0768: ret 
    L_0769: ldloc.0 
    L_076a: ldc.i4.1 
    L_076b: add 
    L_076c: stloc.0 
    L_076d: ret 
    L_076e: ldloc.0 
    L_076f: ldc.i4.1 
    L_0770: add 
    L_0771: stloc.0 
    L_0772: ret 
    L_0773: ldloc.0 
    L_0774: ldc.i4.1 
    L_0775: add 
    L_0776: stloc.0 
    L_0777: ret 
    L_0778: ldloc.0 
    L_0779: ldc.i4.1 
    L_077a: add 
    L_077b: stloc.0 
    L_077c: ret 
    L_077d: ldloc.0 
    L_077e: ldc.i4.1 
    L_077f: add 
    L_0780: stloc.0 
    L_0781: ret 
    L_0782: ldloc.0 
    L_0783: ldc.i4.1 
    L_0784: add 
    L_0785: stloc.0 
    L_0786: ret 
    L_0787: ldloc.0 
    L_0788: ldc.i4.1 
    L_0789: add 
    L_078a: stloc.0 
    L_078b: ret 
    L_078c: ldloc.0 
    L_078d: ldc.i4.1 
    L_078e: add 
    L_078f: stloc.0 
    L_0790: ret 
    L_0791: ldloc.0 
    L_0792: ldc.i4.1 
    L_0793: add 
    L_0794: stloc.0 
    L_0795: ret 
    L_0796: ldloc.0 
    L_0797: ldc.i4.1 
    L_0798: add 
    L_0799: stloc.0 
    L_079a: ret 
    L_079b: ldloc.0 
    L_079c: ldc.i4.1 
    L_079d: add 
    L_079e: stloc.0 
    L_079f: ret 
    L_07a0: ldloc.0 
    L_07a1: ldc.i4.1 
    L_07a2: add 
    L_07a3: stloc.0 
    L_07a4: ret 
    L_07a5: ldloc.0 
    L_07a6: ldc.i4.1 
    L_07a7: add 
    L_07a8: stloc.0 
    L_07a9: ret 
    L_07aa: ldloc.0 
    L_07ab: ldc.i4.1 
    L_07ac: add 
    L_07ad: stloc.0 
    L_07ae: ret 
    L_07af: ldloc.0 
    L_07b0: ldc.i4.1 
    L_07b1: add 
    L_07b2: stloc.0 
    L_07b3: ret 
    L_07b4: ldloc.0 
    L_07b5: ldc.i4.1 
    L_07b6: add 
    L_07b7: stloc.0 
    L_07b8: ret 
}
Re[19]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 15.09.10 07:53
Оценка:
Здравствуйте, hardcase, Вы писали:

ВВ>>1. Ввести опцию компилятора forceSwitch, при которой джамп-таблица генерируется для любого кол-ва вхождений

ВВ>>2. Добавить специальное ключевое слово, атрибут, whatever с теми же целями.
H>Я повторюсь, но это несколько бессмысленно для матчинга по вариантам... Ну не дает оно прироста на 10 вхождениях.

Я про целые.

ВВ>>Чем не нравится вариант с ограничением:

ВВ>>Кстати, пропуски при построении свитча по целым учитываются?
H>Алгоритм закрывает до двух пропусков в матче, как по числам так и по вариантам.

А почему именно два? Какое кол-во пропускает допускает Шарп?
Re[20]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 15.09.10 08:18
Оценка:
Здравствуйте, hardcase, Вы писали:

А для

0
4
5
6

7
..

уже свитча не будет?
Тот же Шарп будет генерировать свитч даже если в первом случае пропуск хоть 1000, может разбить конструкцию на несколько свитчей, использовать комбинацию свитчей, бинарного поиска и пр.

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

В итоге — стоит ли игра свеч? А именно — реализация, при которой компилятор сам решает, когда ему использовать свитч? Свитч — средство оптимизации, так почему бы ему не остаться таковым? ИМХО идеальным вариантом было бы сделать специальный атрибут UseCilSwitch, который можно приставить к матчу — и тогда, и только тогда, компиляция будет происходить в свитч. Это сохранит обратную совместимость, упростит задачу по разработке и Свитч в общем будет тем, чем он на самом деле является — средством оптимизации.
Re[21]: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 15.09.10 08:38
Оценка:
Здравствуйте, Воронков Василий, Вы писали:


ВВ>уже свитча не будет?

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

Скачай исходники, собери компилятор и посмотри — я верю, ты сможешь.
Тема для того и создавалась.
ncc делает кое что из этого, за исключением двоичного поиска, реализовать который не такая уж и простая задача.


ВВ>В итоге — стоит ли игра свеч? А именно — реализация, при которой компилятор сам решает, когда ему использовать свитч? Свитч — средство оптимизации, так почему бы ему не остаться таковым? ИМХО идеальным вариантом было бы сделать специальный атрибут UseCilSwitch, который можно приставить к матчу — и тогда, и только тогда, компиляция будет происходить в свитч.


ВВ>Это сохранит обратную совместимость,

А она терялась?

ВВ>упростит задачу по разработке

Нисколько не упростит, а даже усложнит.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[14]: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 15.09.10 08:48
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Здравствуйте, hardcase, Вы писали:


H>>Здравствуйте, Ka3a4oK, Вы писали:


KK>>>1. небольшие дыры -> таблица с константным временем

KK>>>2. большие дыры -> бинарный поиск(или может даже хэш-таблица при большом количестве элементов)


H>>Что-то я сомневаюсь в том, что C# компилятор производит оптимизацию №2.

H>>На каком количестве разреженных вхождений бинарный поиск будет в среднем быстрее линейного?


ВВ>
ВВ>using System;
ВВ>using System.Collections.Generic;
ВВ>using System.Linq;
ВВ>using System.Text;

ВВ>namespace ConsoleApplication2
ВВ>{
ВВ>    class Program
ВВ>    {
ВВ>        static void Main(string[] args)
ВВ>        {
ВВ>            var x = 5;

ВВ>            switch (x)
ВВ>            {
ВВ>........
ВВ>            }
ВВ>        }
ВВ>    }
ВВ>}
ВВ>


Но это при условии, что логика case-ов исключительно тривиальна.
И если данная конструкция действительно будет востребована, реализовать бинарный поиск я смогу, но сейчас этот пример слишком абстрактен.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[21]: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 15.09.10 08:50
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>В итоге — стоит ли игра свеч? А именно — реализация, при которой компилятор сам решает, когда ему использовать свитч?


Т.е. свич уже не нужен?
/* иЗвиНите зА неРовнЫй поЧерК */
Re[21]: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 15.09.10 08:54
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>В итоге — стоит ли игра свеч? А именно — реализация, при которой компилятор сам решает, когда ему использовать свитч? Свитч — средство оптимизации, так почему бы ему не остаться таковым?


Являясь средством оптимизации он применяется компилятором только тогда, когда его применение оправдано. Управлять "оправданностью" можно с помощью параметров -Oswv и -Oswo.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[15]: CIL switch и сопоставление с образцом
От: Ka3a4oK  
Дата: 15.09.10 09:06
Оценка:
H>Но это при условии, что логика case-ов исключительно тривиальна.
H>И если данная конструкция действительно будет востребована, реализовать бинарный поиск я смогу, но сейчас этот пример слишком абстрактен.

А в чем проблема реализации при нетривиальной логике? И что является мерой тривиальности?
Re[16]: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 15.09.10 09:29
Оценка: +1
Здравствуйте, Ka3a4oK, Вы писали:

H>>Но это при условии, что логика case-ов исключительно тривиальна.

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

KK>А в чем проблема реализации при нетривиальной логике? И что является мерой тривиальности?


Баланс времени выбора и времени исполнения блока.
Если блок складывает два числа, то да, время выбора действия будет превалировать, если же блок вызывает пару-тройку виртуальных функций, то время выбора становится все менее значимым — зачем оптимизировать то, что практически никак не сказывается на производительности?
/* иЗвиНите зА неРовнЫй поЧерК */
Re[10]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.09.10 15:02
Оценка:
Здравствуйте, Ka3a4oK, Вы писали:

KK>Т.е. я правильно ли понимаю, что данное усовершенствование (применение инстуркции switch для патерн матчинга) будет работать только при патерн-матчинге интегральных типов, при этом множество выбора должно быть "без пропусков"?


Нет, не правильно. Пропуски возможны, так как хардкейс реализовал забивку небольшого числа пропусков переходами на default-обработчик.

Кроме того switch генерируется и для вариантов. При этом у базового типа (самого варианта) вызывается виртуальный метод возвращающий целочисленный идентификатор. Кроме того делается проверка на null. Именно эти телодвижения приводят к тому, что паттерн-матчинг по вариантам незначительно замедлился. И именно для этого случая хардкейс ввел константу (12) минимального идущего подряд числа значений.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[12]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.09.10 15:05
Оценка:
Здравствуйте, Ka3a4oK, Вы писали:

KK>2. большие дыры -> бинарный поиск(или может даже хэш-таблица при большом количестве элементов)


Хэш-таблица для целых — это очень не эффективное решение.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[13]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.09.10 15:06
Оценка:
Здравствуйте, hardcase, Вы писали:

H>На каком количестве разреженных вхождений бинарный поиск будет в среднем быстрее линейного?


Теоретически при количестве элементов большем чем 4. На практике, думаю, разницу можно будет заметить только на 30, а то и на 100 элементах.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[16]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.09.10 15:10
Оценка:
Здравствуйте, Ka3a4oK, Вы писали:

KK>А в чем проблема реализации при нетривиальной логике? И что является мерой тривиальности?


Проблема реализации — время на ее реализацию и тестирование.

Хардкейс же говорит о том, что овчинка скорее всего не будет стоить выделки. Бинарный поиск не даст сущетвенного выигрыша по сравнению с линейным просто потому, что на небольшом количестве элементов (что является самым частым случаем) разница не будет заметна в микроскоп, а на фоне вычислений внутри самих обработчиков ее вообще заметно не будет.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[17]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.09.10 15:12
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Баланс времени выбора и времени исполнения блока.

H>Если блок складывает два числа, то да, время выбора действия будет превалировать, если же блок вызывает пару-тройку виртуальных функций, то время выбора становится все менее значимым — зачем оптимизировать то, что практически никак не сказывается на производительности?

К сожалению тут без тестов ничего сказать нельзя. Мое предположение — разница будет не значительна, но может оказаться более значимой на программах с автогенерируемыми матчами (опять же в качестве примера возьмем генераторы ДКА).
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[12]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.09.10 15:17
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

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


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

Какие еще у тебя вопросы тут возникают?

ВВ>>>Вызывается всегда один и тот же case 3. Выборка идет не по переменной цикла, а по переменной х.

VD>>А где гарантия, что код метода не заинлайнен, и что все свитч не выкинут к чертям?

ВВ>Какой метод? Методы со свитчами не инлайнятся.


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

Короче — это очередная синтетика на которую я даже смотреть не хочу. К рассмотрению принимаются только осмысленные алгоритмы или полноценные приложения. А то что синтетика ровным счтетом ничего не показывает я понял еще десять лет тому назад.

Подумай сам. Глупо ведь на основании синтетических тестов вводить оптимизации которые замедляют реальные приложения?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[20]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.09.10 15:22
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Здравствуйте, VladD2, Вы писали:


VD>>Проверяй.


ВВ>Вот тут за меня, оказывается, уже проверили:

ВВ>http://stackoverflow.com/questions/44905/c-switch-statement-limitations-why#48060

И? Какого-то невероятного роста затрат я не вижу. Ежу понятно, что чем больше кода, тем дольше он выполняется. Тупое чтение одной ячейки кэша против чтения нескольких ее линеек, а то и переход на чтение памяти. К тому же кода нет, так что вообще не ясно что обсуждается.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[20]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.09.10 15:23
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Вот тут за меня, оказывается, уже проверили:

ВВ>http://stackoverflow.com/questions/44905/c-switch-statement-limitations-why#48060

Кстати, хотелось бы узнать с чего ты посчитал результаты этих тестов не константными.

Сдается мне ты не верно понимаешь термин константное время доступа.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[20]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.09.10 15:27
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Вот тут за меня, оказывается, уже проверили:

ВВ>http://stackoverflow.com/questions/44905/c-switch-statement-limitations-why#48060

Кстати, для особо упертых цитата из твоей ссылки:

In some cases the compiler will use a CIL switch statement which is indeed a constant time branch using a jump table. However, in sparse cases as pointed out by Ivan Hamilton the compiler may generate something else entirely.

Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[18]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.09.10 15:45
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

VD>>Времени компиляции компилятором своих исходников. Т.е. если в буте бинарники со свитчами, то компиляция одного и того же кода проходит медленнее.


ВВ>Кстати, здесь может играть роль тот фактор, что ДЖИТ не инлайнит методы, в которых есть оп-код Switch.


Может. Хотя вроде как начиная с 3.5 это не так.

А может быть еще 1000 причин среди которых работа кэша и т.п. Заниматься серьезным анализом (граничащим с кандидатским дисером по сложности) я не намерен. Если у тебя есть лишнее время, то валяй, разберись и выдай народу точные выкладки. Но не надо делать далеко идущих выводов на основании синтетических тестов.

ВВ>Ну и само собой для небольших кейсов Switch может попортить работу предсказателю.


И это тоже возможно.

ВВ> Наконец у вас есть дополнительных cost для свитчей по вариантам — проверка на нуль (ты сам говорил) и вызов виртуального метода, который возвращает код вхождения (?). Для целых эти накладные расходы отсутствуют.


Совершенно верно. Потому хардкейс и разделил константы для свитча по интам и свтича по вариантам.

ВВ>Как обычно я забыл, что в Немерле *все* условные конструции — это матч. И сие, конечно, вносит свои коррективы.


Ага. Наконец то ты стал понимать, что есть куча разных "но" о которых мы иной раз даже не догадываемся.

ВВ>Тут возможно два варианта:


ВВ>1. Ввести опцию компилятора forceSwitch, при которой джамп-таблица генерируется для любого кол-ва вхождений

ВВ>2. Добавить специальное ключевое слово, атрибут, whatever с теми же целями.

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

ВВ>Чем не нравится вариант с ограничением:


ВВ>Спорить, надеюсь, не будешь, что в ряде случаев использование джамп-таблицы вместо цепочки переходов может очень сильно влиять на производительности?


Буду. "Очень сильно" — это преувеличение. В любом случае это будут проценты. Скорее всего даже не десятки.

Тут еще нужно понимать, что немерл — это не язык для людей типа Дворкина которые пытаются выжать биты из любого байта. Немерл — это высокоуровневый язык обеспечивающий приемлемую производительность для большинства задач (сравнимую с шаропом, но не обязательно равную ему). Люди пишущие на немреле скорее всего предпочтут циклу вызов функции высшего порядка. А это уже оврехэд. Другими словами люди пишущие немреле предпочтут небольшой оверхэд, если при этом код окажется проще и короче.

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

При это, конечно, наличие опций компилятора позволяющих изменить значения по умолчанию вряд ли кому-то помешают, а значит вполне приемлемы. Но вот введение специальных операторов — это полнейший перебор. Если кому-то там нужна числодробильная производительность, то лучше выбрать С++, или написать на нем критический к времени выполнения код.

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


Не будет никакого координационного изменения. Будет незначительное изменение.

ВВ>Кстати, пропуски при построении свитча по целым учитываются?


Учитываются. До трех, если не ошибаюсь.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.09.10 15:46
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Также в MSBuild-тасках теперь есть возможность указывать параметры командной строки с помощью тега <CustomArguments>,

H>например:
H>
H><CustomArguments>
H>-Oswv:15 -Oswo:3
H></CustomArguments>
H>


Надо для этого дела и в интеграциях сделать поле специальное!
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[14]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 15.09.10 15:48
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

H>>Что-то я сомневаюсь в том, что C# компилятор производит оптимизацию №2.

H>>На каком количестве разреженных вхождений бинарный поиск будет в среднем быстрее линейного?

ВВ>
ВВ>            switch (x)
ВВ>            {
ВВ>                case 0: x += 1; break;
ВВ>                case 5: x += 1; break;
ВВ>                case 100: x += 1; break;
ВВ>                case 200: x += 1; break;
...
ВВ>


А можно объяснить как приведенный код отвечает на поставленный вопрос?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[15]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 15.09.10 18:59
Оценка:
Здравствуйте, VladD2, Вы писали:

ВВ>>
ВВ>>            switch (x)
ВВ>>            {
ВВ>>                case 0: x += 1; break;
ВВ>>                case 5: x += 1; break;
ВВ>>                case 100: x += 1; break;
ВВ>>                case 200: x += 1; break;
VD>...
ВВ>>


VD>А можно объяснить как приведенный код отвечает на поставленный вопрос?



Данный код отвечает на вопрос:
H>>>Что-то я сомневаюсь в том, что C# компилятор производит оптимизацию №2.
Re[13]: CIL switch и сопоставление с образцом
От: Воронков Василий Россия  
Дата: 16.09.10 06:41
Оценка: +1
Здравствуйте, VladD2, Вы писали:

VD>Подумай сам. Глупо ведь на основании синтетических тестов вводить оптимизации которые замедляют реальные приложения?


А какой прирост (в процентах) скорости работы реального приложения в виде компилятора дала реализация Switch?
Re[14]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.09.10 18:36
Оценка: 1 (1)
Здравствуйте, Воронков Василий, Вы писали:

ВВ>А какой прирост (в процентах) скорости работы реального приложения в виде компилятора дала реализация Switch?


В релизе при константе 12 ~ +5 секунд на двух минутах. При константе 3 ~ -5 секунд.

Короче незначительный.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[14]: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 16.09.10 18:57
Оценка:
Здравствуйте, Воронков Василий, Вы писали:

ВВ>Здравствуйте, VladD2, Вы писали:


VD>>Подумай сам. Глупо ведь на основании синтетических тестов вводить оптимизации которые замедляют реальные приложения?


ВВ>А какой прирост (в процентах) скорости работы реального приложения в виде компилятора дала реализация Switch?


В процентах не считал. Но разница в несколько секунд сборки самого себя.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[15]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.09.10 22:28
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>В релизе при константе 12 ~ +5 секунд на двух минутах. При константе 3 ~ -5 секунд.

VD>Короче незначительный.

Новые данные. При компиляции релиза скорость версии со свитчем выше на 7 сек.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 17.09.10 09:24
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Кстати, у меня тут была одна идея... Вместо использования виртуального метода можно в каждый вариант (в базовый тип) добавлять поле типа int (или даже byte) и инициализировать его для каждого своим значением, и проверять потом именно его.


VD>Это немного увеличит объем памяти занимаемый вариантами и потребует лишний инструкции при создании их экземпляров, но возможно это увеличит скорость ПМ.


Попробовал — стало медленнее (заменил виртуальный вызов обращением к полю _N_VariantCode).
Патч можно забрать тут.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[4]: CIL switch и сопоставление с образцом
От: catbert  
Дата: 17.09.10 11:43
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Попробовал — стало медленнее (заменил виртуальный вызов обращением к полю _N_VariantCode).

H>Патч можно забрать тут.

То есть увеличение потребления памяти на один вариант влияет на производительность сильнее устранения виртуального вызова на один match?
Это хороший урок... значит есть смысл оптимизировать в компиляторе использование памяти.
Re[5]: CIL switch и сопоставление с образцом
От: hardcase Пират http://nemerle.org
Дата: 17.09.10 11:46
Оценка:
Здравствуйте, catbert, Вы писали:

C>Здравствуйте, hardcase, Вы писали:


H>>Попробовал — стало медленнее (заменил виртуальный вызов обращением к полю _N_VariantCode).

H>>Патч можно забрать тут.

C>То есть увеличение потребления памяти на один вариант влияет на производительность сильнее устранения виртуального вызова на один match?

C>Это хороший урок... значит есть смысл оптимизировать в компиляторе использование памяти.

Ну, я не исключаю что у меня просто руки кривые.
/* иЗвиНите зА неРовнЫй поЧерК */
Re[6]: CIL switch и сопоставление с образцом
От: catbert  
Дата: 17.09.10 11:51
Оценка:
Здравствуйте, hardcase, Вы писали:

H>Ну, я не исключаю что у меня просто руки кривые.


Ну, вроде бы в патче ляпов не видно... единственное, может быть прокол в самом тестировании... ты одинаковые версии кода компилировал для измерения производительности?
Re[5]: CIL switch и сопоставление с образцом
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.09.10 19:43
Оценка:
Здравствуйте, catbert, Вы писали:

C>То есть увеличение потребления памяти на один вариант влияет на производительность сильнее устранения виртуального вызова на один match?

C>Это хороший урок... значит есть смысл оптимизировать в компиляторе использование памяти.

Это ничего не значит. Там факторов выше крыши.

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