15

我正在阅读一个关于 c# 代码优化的问题,一个解决方案是将 c++ 与 SSE 结合使用。是否可以直接从 ac# 程序进行 SSE?

4

10 回答 10

17

即将发布的Mono 2.2 版本将支持 SIMD。Miguel de Icaza 在这里写了关于即将推出的功能的博客,API 在这里

尽管将有一个库支持在 Microsoft 的 .NET Windows 运行时下进行开发,但除非您在 Mono 运行时下运行代码,否则它不会具有您正在寻找的性能优势。根据您的情况,这可能是可行的。

更新:Mono 2.2发布

于 2009-01-06T05:20:27.547 回答
7

C# 可以显式进行 SSE 调用吗?

不,C# 不能生成内联 IL,更不用说内联 x86/amd64 程序集了。

如果 SSE 可用,CLR,更具体地说是 JIT,将使用 SSE,而无需在大多数情况下强制使用它。我说得最多是因为我不是 SSE 专家,而且我确信在某些情况下它可能是有益的,而 JIT 不会进行优化。

于 2009-01-06T04:39:32.387 回答
5

SIMD for .NET 将在不久的将来推出。此功能 ATM 需要RyuJIT(.NET 的下一代 JIT 编译器)。

您应该使用Microsoft.Bcl.Simd 包Microsoft.Numerics.Vectors.Vector<T>中的类来利用此功能。示例代码在这里

于 2014-04-04T10:50:45.273 回答
4

根据这个论坛发帖,如果 SSE 在目标机器上可用,MS JIT 编译器会自动使用 SSE。

于 2009-01-06T03:51:05.543 回答
2

如果你有一个“大块”工作要做,最好的办法是使用 MMX/SSE 内在函数用 C++ 编写它,然后制作一个非常简单的 /clr 托管 C++ 类来包装你的功能并将其公开为.net 类。然后您的代码可以像使用普通类一样使用该程序集。

有关 VC 内在函数的更多信息,您可以查看我多年前写的这个小曲子。

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

哦-我假设您实际上是想使用并行函数来加快速度。正如其他人指出的那样 - 如果您只想以更大的块等移动数据,JIT 已经知道如何将 SSE 用于这些基础知识。

于 2009-01-22T00:26:44.167 回答
2

菲利普是正确的。我有另一个较旧的帖子显示了类似但更详细的示例。我实际上已经运行了这段代码,并自己修改了它以向自己证明它有效。我正在考虑在我正在工作的项目中使用这种技术,这就是为什么我要出去看看可能有什么新东西,因为这有点旧了。正如作者暗示的那样,您可以在 C++ 中编写任何您想要的函数,编译它,然后将字节复制到您的 C# 中。

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

我要补充一点,Joe 的 CLI C++ 类也是一个好主意,但是,我认为 sse 编译器标志和 /clr 标志在同一个项目上不兼容。我刚刚验证过:必须在单独的项目中编写高性能代码才能使用 SSE(/arch:sse 或 /arch:sse2)编译器标志,因为 /clr 是不兼容的。做任何比在几个输入上做简单算术更复杂的事情,我认为这是最好的方法。

于 2011-06-14T20:27:47.893 回答
2

最近微软发布了一个用于 C# 的测试版 SIMD 矢量库 ( Microsoft.Bcl.Simd ),它需要安装 RyuJIT CTP,并且仅适用于 Windows 8。

您也可以只使用本机 SSE 库并从 C# 调用它。例如 Yeppp 库,请参阅此 StackOverflow 答案

于 2014-04-19T12:41:57.970 回答
2

终于有可能了。这里的帖子http://blogs.msdn.com/b/dotnet/archive/2014/04/07/the-jit-finally-proposed-jit-and-simd-are-getting-married.aspx

于 2014-09-18T23:25:04.790 回答
1

现代 C# 很好地支持 SIMD/SSE 指令并使它们使用起来相当简单。并非所有指令都受支持。

以下是 uint[] 数组的 SSE .Sum() 示例:

    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 上获得,我维护它。

于 2019-10-11T01:28:06.560 回答
0

当然可以(更重要的问题是 - 你为什么要这样做?把它留给运行时;这就是它的工作)。

C# 允许您将委托映射到内存地址。该内存地址可以包含原始汇编代码。您可以在Michael Giagnocavo 的博客上阅读更多内容。

虽然我自己没有尝试过,但也可以使用Marshal.GetDelegateForFunctionPointer

于 2009-01-06T04:59:48.633 回答