通用和非通用方法之间的性能差异

问题描述 投票:3回答:1

为了举例说明,我们要处理具有不同类型矩阵的线性代数。并且我们有一个自定义的Matrix类,该类实现:

interface IMatrix
{
    double this[int i, int j] { get; set; }
    int Size { get; }
}

我想实现矩阵乘法。我对这两种方法都印象深刻:

static void Multiply<TMatrix>(TMatrix a, TMatrix b, TMatrix result) where TMatrix : IMatrix

static void Multiply(Matrix a, Matrix b, Matrix result)

((当然具有类似的实现方式)将在内部产生完全相同的IL,因此具有相同的性能。事实并非如此:第一个比第二个慢四倍。从IL来看,通用类类似于通过接口进行的调用:

static void Multiply(IMatrix a, IMatrix b, IMatrix result)

我想念什么吗?与直接调用相比,有什么方法可以使泛型获得相同的性能吗?


已安装框架4.8,目标框架:4.7.2(也已通过.Net Core 3测试)

方法实现:

static void Multiply(Matrix a, Matrix b, Matrix result)
{
    for (int i = 0; i < a.Size; i++)
    {
        for (int j = 0; j < a.Size; j++)
        {
            double temp = 0;
            for (int k = 0; k < a.Size; k++)
            {
                temp += a[i, k] * b[k, j];
            }
            result[i, j] = temp;
        }
    }
}

Minimal reproductible example

c# .net generics .net-core .net-4.7.2
1个回答
3
投票

。NET将为所有引用类型仅一次为通用方法生成代码。该代码必须通过IMatrix接口调用,因为各种实现类型可能会使用不同的方法来实现该接口。因此,它只是一个接口调用。

但是,如果将Matrix设为struct而不是class,则JITter将生成通用方法的特定于类型的实现,并且可以优化接口调用。

© www.soinside.com 2019 - 2024. All rights reserved.