2015-09-20 2 views
9

Я пытаюсь использовать System.Numerics.Vector (T) для векторизации алгоритма и использования SIMD-операций CPU. Однако моя реализация вектора была значительно медленнее, чем моя первоначальная реализация. Есть ли уловка для использования векторов, которые, возможно, не были документированы? Конкретное использование здесь - попытаться ускорить Xors из kb данных.Использование вектора <T> для SIMD в универсальной платформе Windows

К сожалению, почти вся документация, которую я могу найти на ней, основана на предварительной версии RyuJIT, и я не знаю, сколько из этого материала переносится на .NET Native.

Когда я проверить разборки во время операции Vector исключающего, он показывает:

00007FFB040A9C10 xor   eax,eax 
00007FFB040A9C12 mov   qword ptr [rcx],rax 
00007FFB040A9C15 mov   qword ptr [rcx+8],rax 
00007FFB040A9C19 mov   rax,qword ptr [r8] 
00007FFB040A9C1C xor   rax,qword ptr [rdx] 
00007FFB040A9C1F mov   qword ptr [rcx],rax 
00007FFB040A9C22 mov   rax,qword ptr [r8+8] 
00007FFB040A9C26 xor   rax,qword ptr [rdx+8] 
00007FFB040A9C2A mov   qword ptr [rcx+8],rax 
00007FFB040A9C2E mov   rax,rcx 

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

Я гарантировал, что я работал с Release, x64, включен оптимизированный код. Я видел подобное поведение с компиляцией x86. Я немного новичок в аппаратном уровне, поэтому возможно, что здесь что-то происходит, что я не понимаю.

Рамочная версия 4.6, Vector.IsHardwareAcclederated является ложным во время выполнения.

Обновление: «Скомпилировать с. NET-инструментальную цепочку» является виновником. Включение этого вызывает Vector.IsHardwareAccelerated == false; Отключение его вызывает Vector.IsHardwareAccelerated == true. Я подтвердил, что когда .NET Native отключен, компилятор создает инструкции AVX, используя регистры ymm. Что приводит к вопросу ... почему SIMD не включен в .NET Native? И есть ли способ изменить это?

Update Tangent: я обнаружил, что причина автоматического SSE-Векторизованные коды массива не выполняются потому, что компилятор вставил команду, которая выглядела, чтобы увидеть, если начало массива было ниже адрес чем один из последних элементов массива, и если это так, просто используйте обычные регистры. Я думаю, что это должно быть ошибкой в ​​компиляторе, потому что начало массива всегда должно быть на более низком адресе, чем его последние элементы по соглашению. Это было частью набора инструкций, проверяющих адреса памяти каждого из массивов операндов, я думаю, чтобы убедиться, что они не перекрываются. Я подал отчет об ошибке Microsoft Connect для этого: https://connect.microsoft.com/VisualStudio/feedback/details/1831117

+0

Какая версия Framework это? Сообщается, что аппаратное ускорение является «истинным»? – usr

+0

Рамочная версия 4.6, а IsHardwareAccelerated возвращает false. –

+0

«Почему SIMD не включен в .NET Native?» Я могу только догадываться: SIMD обрабатывается JIT (компилятор Just-in-time, тот, который преобразуется во время выполнения IL-кода в собственный код). .NET native полностью обходит JIT, создавая чисто родную сборку (без необходимости перевода). Я предполагаю, что они просто не реализовали поддержку SIMD в основной цепочке инструментов .NET. Либо потому, что у них еще не было времени, либо потому, что родной .NET можно было использовать для создания программ, работающих на процессорах, у которых нет регистров SIMD –

ответ

9

Я связался с Microsoft, который разместил контактный адрес для .Net Native вопросов и проблем: https://msdn.microsoft.com/en-us/vstudio/dotnetnative.aspx

Моего вопрос был передан Ян Бирман, директор по разработке программного обеспечения Менеджер в поколение и оптимизации технологий Microsoft Team Код:

в настоящее время .NET Native не оптимизирует библиотеки System.Numerics и опирается на реализацию библиотеки по умолчанию. Это может (по-видимому: будет ) привести к коду, написанному с использованием System.Numerics, чтобы не выполнять как в .NET. Родной, как и против других реализаций CLR.

Хотя это несчастливо, .NET Native поддерживает автоматическую векторию , которая поставляется с использованием оптимизаций C++, упомянутых выше. текущая поставка.NET Native компилятор поддерживает SSE2 ISA в своей автотеграции на x86 и x64 и NEON ISA на ARM.

Он также упомянул, что они хотят передать с компилятора C++ возможность генерации всех векторных инструкций (AVX, SSE и т. Д.) И ветви на основе обнаружения набора команд во время выполнения.

Затем он предположил, что, если использование инструкций действительно имеет решающее значение, компонент может быть построен на C++, который имеет доступ к внутренним свойствам компилятора (и, предположительно, этой способности к ветвлению?), А затем легко сопрягается с остальным приложением C#.

Что касается пропущенных инструкций SSE2, все, что мне нужно было сделать, чтобы заставить его скомпилировать нужные инструкции, было заменить петлю «a = a^b» на «a^= b». Поскольку они должны быть эквивалентными выражениями, кажется, что это ошибка, но, к счастью, с обходным решением.

+0

Очень интересная/полезная информация, спасибо за продолжение! –

+1

Спасибо, что вернулся. Это было не то, что я искал, но, тем не менее, увлекательно. Кудо за то, чтобы следить за этим для всех нас. – EndsOfInvention