Pull to refresh
-2

User

0,1
Rating
Send message

Ну ладно, на вкус и цвет, как говорится.

Если будет не лень, пожалуйста, вкратце - какие конкретно механизмы и почему? И чем они предпочтительнее того же ЕФ.

Мне для общего развития и понимания.

И что? Усложняет миграцию с Джавы?

Я просто пытаюсь понять, в чём собственно этот "минус".

Из минусов шарпа - это отсутствие популярного ORM фреймворка, реализующего спецификацию JPA .

Чисто из любопытства: а зачем оно в НЕТе?

Что, не приведёт имплицитно инт в флоту?
Я не специалист, на с# приводит и результат ожидаемо лучший.

...побитовые операции с флотом тоже вполне себе существуют.

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

А так, ещё можно вместо умножения попробовать делать - (отрицание) и & (побитовое И).

Можно, и даже побитовое NOT. Всё это можно сделать без ветвлений, парой-тройкой арифметических/битовых операций. Иногда ОЧЕНЬ ускоряет, иногда - нет.

Тут ещё стоит не забывать про буферы декодера и блока обработки циклов (как его там) - там сдвиг команд на пару байтов туда-сюда может СИЛЬНО влиять на производительность.

vpcompressd

Да, пропустил, спасибо за науку.

Жаль, что нарочно на такое .NET JIT (пока) не спровоцировать, мне бы пригодилось кое-где.

Именно так. Загрузили вектор в регистр, одной инструкцией сравниваем значения с заранее подговленным вектором с размноженной константой, другой копируем подходящие в выходной массив (подряд).

Можно по-подробнее, псевдокод?

Векторизировать условное поэлементное копирование?

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

То есть, здесь только разработчик может знать, что значения. к примеру, отсортированы - и тогда нужен ИФ с ранним выходом, или "почти отсортированы", и тогда код как в примере будет оптимальным, или вообще непредсказуемые, и тогда нужен оптимизированный вариант из примера.
Тут только JIT PGO мог бы по ходу дела переписывать асм, вопрос - не было бы это дороже, чем прогонять цикл как написано.

А так-то да, "его разработчики подумали" о многом. иной раз читаешь релиз ноутс и диву даёшься. Но всего на их уровне не придумаешь.

smlen = 0;for (int i = 0; i < 1000; i++) { if (numbers[i] < 500) { small_numbers[smlen] = numbers[i]; smlen += 1; }}

А о чём конкретно в случае изначального примера должен думать разработчик компилятора?

И что в нём такого, что его нужно прям анализировать и предсказывать [особенно Инженеру встраиваемых систем (младшему)]?

Не надо добавлять if-ы, чтобы избежать немного арифметики. Вот главное, что нужно

Даже не вспоминаем о возможном "лишнем" обращении к незакешированной памяти для обеспечения чистой арифметики, с этим и так понятно.

Но вот у меня есть живой пример, в котором с помощью ИФа можно ИНОГДА избавиться от простого int64 idiv над операндами, гарантированно лежащими в регистре и кеш-линии. И оно того стоит - любые бенчмарки и реальность это подтверждают.

Так что не всякая арифметика одинаково полезна.

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

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

?: оптимизируется лучше чем if?

Зависит от компилятора/JITа, но на уровне команд процессоров Интела, вполне может компилироваться как бранчлесс.
Однако тут есть нюанс: сначала оба операнда читаются из памяти, потом один из них выбирается. Если чтение не из кешей - то бранч может оказаться выгоднее.

Отличный вопрос, меня он тоже тревожит. По опыту - нет, хотя объяснить я себе этого не могу.
Но: с обратным циклом и пойнтер-арифметикой (ref var curr + MemoryMarshal + Unsafe.Add) можно и от регистра для exit condition избавиться, и доступ прямой последовательный сохранить. И JIT именно так и делает, когда решает, что может поменять направление счётчика.

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

Есть. Даже c# код под Интел экономит регистр на обратных циклах.

Типа такого будет:

L0027	dec	r8d
L002a	jns	short L0020

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

На х86/64 тоже, чего бы ему не сэкономить.

Бывает.

Поведение странное только если вдруг упёрся в производительность, но тогда сам бог велел изучить вопрос.

А пока не упёрся - что бывает в 99% случаев - отличный прозрачный safeguard.

И как предлагаете IList и ReadOnlyCollection приводить к спану?

1
23 ...

Information

Rating
3,783-rd
Registered
Activity