2

我正在尝试使用 MiscUtils 实现一些通用数学类。示例代码不使用 MiscUtils,只是简单地包装了一个类型,它存在一些主要的性能问题:

在内置值类型上使用数学至少快 15 倍。简单地将值类型包装在结构中大约慢 2 倍。使用动态绕过运算符类型约束大约慢 30 倍!!!!

我的目标是有一个简单的类

class Vector<T> { ... }

并且能够使用 Vector 之类的东西来添加 T 列表而不会显着影响性能(T 将是原始类型)。

结果:

带调试的调试模式:

    V  = 1.0x    (Direct ValueType addition)
    WE = 6.4x    (Wrapped ValueType empty addition)
    WA = 17.9x   (Wrapped ValueType MiscUtils addition)
    D  = 17.8x   (Dynamic ValueType addition)
    DE = 37.1x   (Dynamid Wrapped Valuetype empty addition)
    DA = 37.7x   (Dynamid Wrapped Valuetype MiscUtils addition)

无需调试的释放模式:

V  - 0.36s
WE - 0.27s
WA - 1.25s
D  - 1.34s
DE - 7.74s
DA - 7.22s
    V  = 1.3x
    WE = 1.0x
    WA = 4.5x
    D  = 4.9x
    DE = 28.2x
    DA = 26.3x

V  - 0.18s
WE - 0.14s
WA - 0.62s
D  - 0.66s
DE - 3.01s
DA - 3.65s
    V  = 1.3x
    WE = 1.0x
    WA = 4.5x
    D  = 4.8x
    DE = 21.9x
    DA = 26.6x

V  - 0.12s
WE - 0.09s
WA - 0.41s
D  - 0.44s
DE - 2.17s
DA - 2.42s
    V  = 1.3x
    WE = 1.0x
    WA = 4.4x
    D  = 4.8x
    DE = 23.7x
    DA = 26.5x

无论如何,可以看出 MiscUtils 比预期的要慢(网站说几个百分比)并且动态非常糟糕。

任何想法发生了什么或如何改善结果?

#define __MiscUtils
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
#if __MiscUtils
using MiscUtil;
#endif

namespace GenericNumerics
{

    struct num1<T> where T : struct
    {
        public readonly T a;
        public num1(T v) { a = v; }
        public static num1<T> operator +(num1<T> c1, num1<T> c2) { return new num1<T>(); }
        public static implicit operator num1<T>(T d) { return new num1<T>(); }
    }
    #if __MiscUtils
    struct num2<T> where T : struct
    {
        public readonly T a;
        public num2(T v) { a = v; }
        public static num2<T> operator +(num2<T> c1, num2<T> c2) { return Operator.Add(c1.a, c2.a); }
        public static implicit operator num2<T>(T d) { return new num2<T>(); }
    }
    #endif


    class Program
    {
        public static Stopwatch Stopwatch = new Stopwatch();



        static void Main(string[] args)
        {
            var cntV = 0L; var cntWE = 0L; var cntWA = 0L; var cntD = 0L; var cntDE = 0L; var cntDA = 0L;
            double time = 2000;         

            for (int k = 0; k < 1; k++)
            {

                {
                    Console.Write("V  - ");
                    var x = 1D; var y = 0D; var z = 0D;
                    Stopwatch.Restart();
                    while(Stopwatch.ElapsedMilliseconds < time)
                    {
                        x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
                        x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
                        cntV++;
                    }
                    Console.WriteLine(String.Format("{0:0.00}s", time/cntV*1000));
                }

                {
                    Console.Write("WE - ");
                    num1<double> x = 1D; num1<double> y = 0D; num1<double> z = 0D;
                    Stopwatch.Restart();                    
                    while (Stopwatch.ElapsedMilliseconds < time)
                    {
                        x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
                        x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
                        cntWE++;
                    }
                    Console.WriteLine(String.Format("{0:0.00}s", time / cntWE * 1000));
                }

                #if __MiscUtils
                {
                    Console.Write("WA - ");
                    num2<double> x = 1D; num2<double> y = 0D; num2<double> z = 0D;
                    Stopwatch.Restart();
                    while (Stopwatch.ElapsedMilliseconds < time)
                    {
                        x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
                        x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
                        cntWA++;
                    }
                    Console.WriteLine(String.Format("{0:0.00}s", time / cntWA * 1000));
                }
                #endif

                {
                    Console.Write("D  - ");
                    dynamic x = 1D; dynamic y = 0D; dynamic z = 0D;
                    Stopwatch.Restart();
                    while (Stopwatch.ElapsedMilliseconds < time)
                    {
                        x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
                        x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
                        cntD++;
                    }
                    Console.WriteLine(String.Format("{0:0.00}s", time / cntD * 1000));
                }

                #if __MiscUtils
                {
                    Console.Write("DE - ");
                    dynamic x = new num2<double>(0); dynamic y = new num2<double>(0); dynamic z = new num2<double>(0);
                    Stopwatch.Restart();
                    while (Stopwatch.ElapsedMilliseconds < time)
                    {
                        x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
                        x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
                        cntDE++;
                    }
                    Console.WriteLine(String.Format("{0:0.00}s", time / cntDE * 1000));
                }

                {
                    Console.Write("DA - ");
                    dynamic x = new num2<double>(0); dynamic y = new num2<double>(0); dynamic z = new num2<double>(0);
                    Stopwatch.Restart();
                    while (Stopwatch.ElapsedMilliseconds < time)
                    {
                        x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
                        x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z; x = x + z; x = y + z; z = x + z; x = x + z; x = y + z; y = y + z; z = x + z;
                        cntDA++;
                    }
                    Console.WriteLine(String.Format("{0:0.00}s", time / cntDA * 1000));
                }
                #endif

                var m = (double)Math.Max(cntV, Math.Max(cntWE, Math.Max(cntWA, Math.Max(cntD, Math.Max(cntDE, cntDA)))));
                Console.WriteLine(string.Format("\tV  = {0:0.0}x\n\tWE = {1:0.0}x\n\tWA = {2:0.0}x\n\tD  = {3:0.0}x\n\tDE = {4:0.0}x\n\tDA = {5:0.0}x\n", m / cntV, m / cntWE, m / cntWA, m / cntD, m / cntDE, m / cntDA));
            }

            Console.ReadKey();
            return;
        }
    }
}
4

0 回答 0