Подтвердить что ты не робот

Использование SSE в С# возможно?

Я читал вопрос о оптимизации кода С#, и одним из решений было использование С++ с SSE. Можно ли выполнить SSE непосредственно из программы С#?

4b9b3361

Ответ 1

Предстоящая Mono версия 2.2 будет иметь поддержку SIMD. Miguel de Icaza рассказал о предстоящей функции здесь, а API здесь.

Хотя будет библиотека, которая будет поддерживать разработку в среде исполнения Microsoft.NET Windows, она не будет иметь преимуществ производительности, которые вы ищете, если вы не запустите код в режиме исполнения Mono. Что может быть выполнимо в зависимости от ваших обстоятельств.

Обновление: Mono 2.2 выпущено

Ответ 2

Может ли С# явно вызвать вызов SSE?

Нет. С# не может создать встроенный IL гораздо меньше встроенной сборки x86/amd64.

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

Ответ 3

SIMD для .NET будет доступен в ближайшем будущем. RyuJIT (компилятор JIT следующего поколения для .NET), необходимый для этой функции ATM.

Вы можете использовать класс Microsoft.Numerics.Vectors.Vector<T> из пакет Microsoft.Bcl.Simd, чтобы воспользоваться этой возможностью. Пример кода здесь.

Ответ 4

Основываясь на этот форум, компилятор MS JIT автоматически использует SSE, если SSE доступно на целевой машине.

Ответ 5

Если у вас есть "кусок" работы, которую вы хотите сделать, лучше всего написать ее на С++ с использованием встроенных MMX/SSE-функций, а затем создать очень простой/управляемый CLM-класс, который обертывает вашу функциональность и предоставляет ее как класс .net. Тогда ваш код может просто использовать эту сборку, как если бы это был обычный класс.

Для получения дополнительной информации о VC intrinsics вы можете посмотреть на эту маленькую мелодию, которую я написал много лет назад.

http://msdn.microsoft.com/en-us/library/0aws1s9k.aspx

О, я предполагаю, что вы на самом деле хотите использовать параллельные функции, чтобы что-то ускорить. Как указывали другие, если вы просто хотите переместить данные в более крупные куски и т.п., JIT уже знает, как использовать SSE для этих основ.

Ответ 6

Филипп прав. У меня есть еще одна, более старая статья с похожим, но более подробным примером. Я действительно запускаю этот код и сам модифицировал его, чтобы доказать, что он работает. Я рассматриваю использование этой техники в проекте, в котором я работаю, и поэтому я ищу, чтобы увидеть, что может быть новым, так как это немного устарело. Как предполагает автор, вы можете написать любую функцию, которую вы хотите на С++, скомпилировать ее, а затем скопировать байты в ваш С#.

http://blogs.msdn.com/b/devinj/archive/2005/07/12/438323.aspx

Я бы добавил, что класс Joe CLI С++ тоже хорошая идея, однако я не думаю, что флаг sse-компилятора и флаг /clr совместимы в одном проекте. Я просто подтвердил, что: нужно написать свой высокопроизводительный код в отдельном проекте, чтобы использовать флаг компилятора SSE (/arch: sse или /arch: sse2), поскольку /clr несовместим. Чтобы сделать что-либо гораздо более сложное, чем простая арифметика на нескольких входах, я считаю, что это лучший подход.

Ответ 7

Недавно Microsoft выпустила бета-библиотеку SIMD (Microsoft.Bcl.Simd) для С#, которая требует установки RyuJIT CTP и работает только с Windows 8.

Вы также можете использовать собственную SSE-библиотеку и вызывать ее из С#. Например, библиотека Yeppp, см. fooobar.com/questions/157316/....

Ответ 9

Современный С# хорошо поддерживает инструкции SIMD/SSE и делает их довольно простыми в использовании. Не все инструкции еще поддерживаются.

Вот пример SSE.Sum() массива uint []:

    using System.Numerics;

    private static ulong SumSseInner(this uint[] arrayToSum, int l, int r)
    {
        var sumVectorLower = new Vector<ulong>();
        var sumVectorUpper = new Vector<ulong>();
        var longLower      = new Vector<ulong>();
        var longUpper      = new Vector<ulong>();
        int sseIndexEnd = l + ((r - l + 1) / Vector<uint>.Count) * Vector<uint>.Count;
        int i;
        for (i = l; i < sseIndexEnd; i += Vector<int>.Count)
        {
            var inVector = new Vector<uint>(arrayToSum, i);
            Vector.Widen(inVector, out longLower, out longUpper);
            sumVectorLower += longLower;
            sumVectorUpper += longUpper;
        }
        ulong overallSum = 0;
        for (; i <= r; i++)
            overallSum += arrayToSum[i];
        sumVectorLower += sumVectorUpper;
        for (i = 0; i < Vector<long>.Count; i++)
            overallSum += sumVectorLower[i];
        return overallSum;
    }

Эта конкретная функция является частью бесплатного пакета nuget HPCsharp, доступного на nuget.org, который я поддерживаю.

Ответ 10

Конечно, вы можете (более важный вопрос - почему бы вам просто оставить его во время выполнения, что его работа).

С# позволяет сопоставить делегат с адресом памяти. Этот адрес памяти может содержать необработанные коды сборки. Вы можете больше узнать о блог Майкла Джагнаково.

Хотя я и не пробовал себя, возможно использовать Marshal.GetDelegateForFunctionPointer.