Проблемы с двухъядерным кодом Qualcomm Scorpion ARM NEON?

Я разрабатываю нативную библиотеку для Android, где использую оптимизации сборки ARM и многопоточность, чтобы получить максимальную производительность на двухъядерном чипсете ARM MSM8660. Делая некоторые замеры, я заметил следующее:

  1. Однопоточная библиотека с оптимизацией NEON быстрее, чем однопоточная библиотека с ARMv6< /strong> оптимизация (как и ожидалось).
  2. Многопоточная библиотека с оптимизацией ARMv6 быстрее, чем однопоточная библиотека с ARMv6< /strong> оптимизация (как и ожидалось).
  3. Многопоточная библиотека с оптимизацией NEON работает медленнее, чем однопоточная библиотека с NEON< /strong> оптимизации (определенно не ожидаемые!).

Я пробовал искать по всей сети объяснение, почему это так, но до сих пор не нашел. Кажется, что все ядра используют один и тот же конвейер NEON или что-то в этом роде, но все схемы указывают на то, что каждое ядро ​​должно иметь свой собственный блок NEON. Кто-нибудь знает, почему это происходит?


person Leo    schedule 29.09.2011    source источник


Ответы (3)


Прежде всего, какую библиотеку вы используете?

Вы правы, каждое ядро ​​​​имеет свой собственный блок NEON. Однако это их собственный проприетарный блок «VeNum», и о нем не так много информации. Он был разработан для Scorpion на базе Cortex-A8 в формате 8x50 и был намного лучше, чем у ARM. собственная реализация NEON SIMD. Однако хорошим облегчением является то, что они (qcom) проектируют свое оборудование таким образом, чтобы оно было совместимо с базовым дизайном refrence, поэтому большая часть кода для cortex-A8 будет прекрасно работать со Scorpion, хотя и с некоторым снижением производительности из-за к возможному различному времени обучения.

Если вы используете «softfp» для компиляции своей программы, у вас будет накладные расходы примерно в 20 циклов для каждой вызываемой вами функции, которая использует аргументы с плавающей запятой и/или использует модуль NEON для передачи регистровых данных из ядра ARM в модуль Neon и наоборот, довольно медленный и иногда может останавливать ядро ​​​​на много циклов, ожидая сброса конвейера.

Также для многопоточной программы, использующей модуль с плавающей запятой, ядро ​​​​должно сохранять регистры FP во время переключения контекста, что влечет за собой дополнительные штрафы для потоков, поскольку мы уже знаем, что перемещение регистров из neon в arm происходит медленно и, как известно, останавливает конвейер.

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

person sgupta    schedule 05.08.2012

Это, вероятно, из-за промахов кеша. Трудно сказать без дополнительной информации.

person onemasse    schedule 02.10.2011
comment
Другой способ выразить это так: узким местом, вероятно, является пропускная способность внешней памяти, и в этом случае добавление большего количества ядер не помогает. - person Guy Sirton; 02.10.2011
comment
Да, но если бы дело было только в пропускной способности внешней памяти, производительность должна быть как минимум равной. Конечно, добавление большего количества потоков приведет к большему переключению контекста, хотя я не уверен, насколько это повлияет на производительность. - person onemasse; 03.10.2011

Я предполагаю, что это из-за штрафа за дополнительный цикл, связанный с промывкой конвейера NEON. Конвейер NEON отстает от остальной части ядра, поэтому вы видите дополнительный штраф за пропущенные ветки и так далее.

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

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

person Anthony Blake    schedule 25.11.2011