Как я могу кодировать Java для разрешения устранения использования и граничной проверки SSE (или другая усовершенствованная оптимизация)?

( Обновление : Полная поддержка агрегирования ORM теперь включена в Django 1.1. Верный для ниже предупреждения об использовании частных API, метод, зарегистрированный здесь больше, не работает в пост1.1 версиях Django. Я не закопал для выяснения почему; если Вы находитесь на 1,1, или позже необходимо использовать реальное агрегирование API так или иначе.)

базовая поддержка агрегирования уже была там в 1,0; это просто не документировано, не поддерживается, и еще не имеет дружественного API сверху его. Но вот то, как можно использовать его так или иначе, пока 1.1 не прибывает (на Ваш собственный риск, и в полном знании, что атрибут запроса group_by не является частью общедоступного API и мог измениться):

query_set = Item.objects.extra(select={'count': 'count(1)'}, 
                               order_by=['-count']).values('count', 'category')
query_set.query.group_by = ['category_id']

, Если Вы тогда выполняете итерации по query_set, каждое возвращенное значение будет словарем с ключом "категории" и ключом "количества".

Вы не должны заказывать - количество здесь, это просто включено, чтобы продемонстрировать, как оно сделало (оно должно быть сделано в .extra () вызов, не в другом месте в queryset цепочке конструкции). Кроме того, Вы могли точно также сказать количество (идентификатор) вместо количества (1), но последний может быть более эффективным.

Примечание также, что при установке .query.group_by, значения должны быть фактическими именами столбцов DB ('category_id') не имена полей Django ('категория'). Это вызвано тем, что Вы настраиваете внутренности запроса на уровне, где все находится в терминах DB, не условиях Django.

40
задан P̲̳x͓L̳ 3 June 2018 в 17:19
поделиться

4 ответа

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

Знай своего врага

Вы нацелены на комбинацию JVM (по сути, JIT) и базовая подсистема ЦП / памяти. Таким образом, фраза «Это быстрее на JVM X» вряд ли будет правильным во всех случаях, поскольку вы переходите к более агрессивной оптимизации.

Если ваш целевой рынок / приложение будет в основном работать на определенной архитектуре, вам следует подумать об инвестировании в инструменты, специфичные для Это. * Если ваша производительность на x86 является критическим фактором, то Intel VTune отлично подходит для детализации описанного вами вида jit output analysis . * Различия между 64-битными и 32-битными JIT могут быть значительными, особенно на платформах x86, где соглашения о вызовах могут изменяться и возможности регистрации сильно различаются.

Получите правильные инструменты

Вероятно, вы захотите чтобы получить профилировщик выборки. Накладные расходы на инструменты (и связанный с этим удар по таким вещам, как встраивание, загрязнение кеша и увеличение размера кода) для ваших конкретных потребностей были бы слишком большими. Анализатор Intel VTune действительно может использоваться для Java, хотя интеграция не такая тесная, как другие.
Если вы используете Sun JVM и счастливы только тем, что знаете, что делает последняя / самая лучшая версия, тогда параметры, доступные для , для исследования вывода JIT значительны, если вы немного разбираетесь в ассемблере. В этой статье подробно рассказывается о некоторых интересных анализах с использованием этой функциональности.

Изучение других реализаций

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

Некоторые особенности

Поскольку LZF в эффективной неуправляемой реализации на современных настольных процессорах CPUS в значительной степени ограничен пропускной способностью памяти ( следовательно, он конкурирует со скоростью неоптимизированного memcpy) вам понадобится код, чтобы полностью оставаться в кэше уровня 1.
Таким образом, любые статические поля, которые вы не можете преобразовать в константы, должны быть помещены в один и тот же класс, поскольку эти значения часто будут помещаться в одну и ту же область памяти, выделенную для vtables и метаданных, связанных с классами.

Распределение объектов, которые не могут быть перехвачены by Escape Analysis (только в версии 1.6 и выше) необходимо избегать.

Код c агрессивно использует развертывание цикла. Однако производительность этого на старых (эпоха 1.4) виртуальных машинах сильно зависит от режима, в котором находится JVM . По-видимому, последние версии sun jvm более агрессивны при встраивании и развертывании, особенно в серверном режиме.

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

«Это идет прямо. для нас "

Ваша цель движется, и продолжу. Опять же, предыдущий опыт Марка Леманна:

размер HLOG по умолчанию теперь равен 15 (кеши процессора увеличены)

Даже незначительные обновления jvm могут включать значительные изменения компилятора

6544668 Операции с массивами, которые могут не выравниваются во время выполнения. 6536652 Реализовать оптимизацию сверхслова (SIMD) 6531696 не использовать немедленное сохранение 16-битных значений в памяти на процессоре Intel 6468290 Разделение и распределение вне eden на основе процессора

Captain Obvious

Измерение, измерение, измерение. ЕСЛИ вы можете заставить свою библиотеку включать (в отдельной dll) простой и легкий в выполнении тестовый тест, который регистрирует соответствующую информацию (версия vm, процессор, ОС, параметры командной строки и т. Д.) И упрощает отправку вам обратно. увеличьте охват, лучше всего вы будете покрывать тех людей, которые заботятся о нем.

18
ответ дан 27 November 2019 в 01:57
поделиться

Что касается исключения проверки границ , я полагаю, что новый JDK уже будет включать улучшенный алгоритм, который устраняет его, когда это возможно. Это две основные статьи по этой теме:

  • V. Михеев, С. Федосеев, В. Сухарев, Н. Липский. 2002 г. Эффективное улучшение управления версиями цикла в Java . Ссылка . Эта статья написана ребятами из Excelsior, которые реализовали эту технику в своей JVM Jet
  • Würthinger, Thomas, Christian Wimmer и Hanspeter Mössenböck. 2007. Устранение проверки границ массива для клиентского компилятора Java HotSpot . PPPJ. Ссылка . Слегка основанная на вышеупомянутой статье, я полагаю, что эта реализация будет включена в следующий JDK . Также представлены достигнутые ускорения .

Есть также эта запись в блоге, в которой поверхностно обсуждается одна из статей, а также представлены некоторые результаты сравнительного анализа не только для массивов, но и для арифметики в новом JDK. Комментарии к записи в блоге тоже очень интересные, поскольку авторы вышеуказанных статей представляют очень интересные комментарии и обсуждают аргументы. Кроме того, есть несколько указателей на другие похожие сообщения в блогах по этой теме.

Надеюсь, это поможет.

7
ответ дан 27 November 2019 в 01:57
поделиться

It's rather unlikely that you need to help the JIT compiler much with optimizing a straightforward number crunching algorithm like LZW. ShuggyCoUk mentioned this, but I think it deserves extra attention:

The cache-friendliness of your code will be a big factor.

You have to reduce the size of your woking set and improve data access locality as much as possible. You mention "packing bytes into ints for performance". This sounds like using ints to hold byte values in order to have them word-aligned. Don't do that! The increased data set size will outweigh any gains (I once converted some ECC number crunching code from int[] to byte[] and got a 2x speed-up).

On the off chance that you don't know this: if you need to treat some data as both bytes and ints, you don't have to shift and |-mask it - use ByteBuffer.asIntBuffer() and related methods.

With current 1.6 JVM, how many элементы должны быть скопированы перед System.arraycopy превосходит цикл копирования?

Лучше провести тест самостоятельно. Когда я делал это еще в Java 1.3 раза, это было где-то около 2000 элементов.

3
ответ дан 27 November 2019 в 01:57
поделиться

На данный момент ответов много, но есть пара дополнительных вещей:

  • Измерение, измерение, измерение. Несмотря на то, что большинство разработчиков Java предостерегает от микротестирования, обязательно сравнивайте производительность между изменениями. Оптимизации, которые не приводят к измеримым улучшениям, обычно не заслуживают сохранения (конечно, иногда это комбинация вещей, и это становится сложнее)
  • Тесные циклы важны как для Java, так и для C (и то же самое с распределением переменных - хотя вы не контролируете его напрямую, HotSpot в конечном итоге должен будет это сделать). Мне удалось практически удвоить скорость декодирования UTF-8, переставив жесткий цикл для обработки однобайтовых регистров (7-битный ascii) как жесткий (er) внутренний цикл, исключив другие случаи.
  • Не стоит недооценивать стоимость выделения и / или очистки больших массивов - если вы хотите, чтобы кодирование / декодирование lzf было быстрее и для небольших / средних фрагментов (не только размером в мегабайт), имейте в виду, что ВСЕ выделения байта [] / int [] несколько дорого обходятся; не из-за GC, а потому, что JVM ДОЛЖНА очищать пространство.

Реализация H2 также была немного оптимизирована (например: она больше не очищает хэш-массив, это часто имеет смысл); и я действительно помог изменить его для использования в другом проекте Java. Мой вклад в основном состоял в том, чтобы изменить его, чтобы он был более оптимальным для случая без потоковой передачи, но это не коснулось жестких циклов кодирования / декодирования.

но поскольку JVM ДОЛЖНА очищать пространство.

Реализация H2 также была немного оптимизирована (например: она больше не очищает хэш-массив, это часто имеет смысл); и я действительно помог изменить его для использования в другом проекте Java. Мой вклад в основном состоял в том, чтобы изменить его, чтобы он был более оптимальным для случая без потоковой передачи, но это не коснулось жестких циклов кодирования / декодирования.

но поскольку JVM ДОЛЖНА очищать пространство.

Реализация H2 также была немного оптимизирована (например: она больше не очищает хэш-массив, это часто имеет смысл); и я действительно помог изменить его для использования в другом проекте Java. Мой вклад в основном состоял в том, чтобы изменить его, чтобы он был более оптимальным для случая без потоковой передачи, но это не коснулось жестких циклов кодирования / декодирования.

2
ответ дан 27 November 2019 в 01:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: