解决 两个几乎相同的线程,性能差异很大

已加入
2020年11月24日
留言内容
8
编程经验
10+
我在C#中拥有一个大型多线程系统,我意识到两个线程之间的性能差异很大。
现在,我设计了两个几乎完全相同的线程,其中一个线程的执行速度提高了4-5倍(并且如果您更改了它们必须运行的循环数量,它会线性扩展)。
和区别?
一种笨拙的条件围绕其中之一的实际重码。
对我来说这没有任何意义,而且如果这么小的细节可能产生如此巨大的影响,我将无能为力地进行优化。
这已在Unity中进行了测试,因此在其他环境中结果可能会有所不同。

ThreadA完成时间:2.8秒。
线程B finish time: 0.6 seconds.


提个醒"ThreadB"是具有条件的条件(在迭代时,该条件将在第一时间立即评估为true)。
如此愚蠢的代码添加如何使实际有效负载(for循环和数字运算)的执行速度如此之快?
另外,如果我更改"delay"带有静态变量"0.0"直接在ThreadB的条件下,它的性能再次类似于ThreadA。
换句话说:一个单精度双精度数,无论是硬编码值还是引用变量,都会使性能差异提高4-5倍。

不用管实际的算法,这只会使计算机处理一些数字。
我知道我要一次又一次地比较相同的数据,这很重要。

我不是编译专家,也没有办法研究实际的机器/汇编代码中的差异。
我只知道两者之间的差异是巨大的,对我来说是无意义的。
我想念什么?
我偶然发现了这一点,将来我可能无法知道给定线程以20%的可能速度执行,只要稍作更改就可以解决。

请。
我需要一个专家来使这一切从纯魔术变为现实"Oh, that's why...!
现在我知道将来如何避免它了...".
我知道C#的编译被托管的东西层包围,但是一定有逻辑上的原因。对?

这是一些测试代码,带有一些简单的结构来支持它。如果有人有时间检查他们是否获得与我相同的结果,我会很高兴。


C#:
using System.Threading;

public class ThreadTest
{
    Thread threadA;
    Thread threadB;

    bool runThreadA = false;
    bool runThreadB = false;

    System.Diagnostics.Stopwatch stopWatch;

    double elapsedTimeA = 0;
    double elapsedTimeB = 0;
    
    public ThreadTest()
    {
        stopWatch = new System.Diagnostics.Stopwatch();
        StartThreads();
    }

    public void StartThreads ()
    {
        stopWatch.Reset();
        stopWatch.Start();
        threadA = new Thread(ThreadA);
        threadB = new Thread(ThreadB);

        runThreadA = true;
        runThreadB = true;

        elapsedTimeA = 0;
        elapsedTimeB = 0;
        threadA.Start();
        threadB.Start();
    }

    void ThreadA ()
    {
        while (runThreadA)
        {
            
            runThreadA = false;
            double preTicks = stopWatch.ElapsedTicks;

            Line3Double lineA = new Line3Double(new Vector3DoublePrecision(10, 20, 30), new Vector3DoublePrecision(100, 140, 180));
            Line3Double lineB = new Line3Double(new Vector3DoublePrecision(-10, -20, -30), new Vector3DoublePrecision(-100, -140, -180));

            int lines = 1000;

            for (int i = 0; i < 8; i++)
            {
                for (int j = 0; j < lines; j++)
                {
                    double aStartX = lineA.startX;
                    double aStartY = lineA.startY;
                    double aStartZ = lineA.startZ;

                    double aEndX = lineA.endX;
                    double aEndY = lineA.endY;
                    double aEndZ = lineA.endZ;

                    double aDirX = lineA.dirX;
                    double aDirY = lineA.dirY;
                    double aDirZ = lineA.dirZ;

                    double aDotSelf = lineA.dotSelf;

                    for (int k = 0; k < 8; k++)
                    {
                        for (int l = 0; l < lines; l++)
                        {
                            double wX = aStartX - lineB.startX;
                            double wY = aStartY - lineB.startY;
                            double wZ = aStartZ - lineB.startZ;

                            double b = aDirX * lineB.dirX + aDirY * lineB.dirY + aDirZ * lineB.dirZ;
                            double d = aDirX * wX + aDirY * wY + aDirZ * wZ;
                            double e = lineB.dirX * wX + lineB.dirY * wY + lineB.dirZ * wZ;

                            double D = aDotSelf * lineB.dotSelf - b * b;
                            double sc, tc;
                            if (D < 0.0000001)
                            {
                                // the lines are almost parallel
                                sc = 0.0f;
                                tc = (b > lineB.dotSelf ? d / b : e / lineB.dotSelf);
                            }
                            else
                            {
                                sc = (b * e - lineB.dotSelf * d) / D;
                                tc = (aDotSelf * e - b * d) / D;
                            }

                            double shortestX = wX + (sc * aDirX) - (tc * lineB.dirX);
                            double shortestY = wY + (sc * aDirY) - (tc * lineB.dirY);
                            double shortestZ = wZ + (sc * aDirZ) - (tc * lineB.dirZ);

                            double 距离 = shortestX * shortestX + shortestY * shortestY + shortestZ * shortestZ;
                        }
                    }
                }
            }

            double postTicks = stopWatch.ElapsedTicks;
            double time = ((postTicks - preTicks) / System.Diagnostics.Stopwatch.Frequency) * 1000;
            elapsedTimeA = time;
        }
    }

    void 线程B()
    {
        long startTicks = stopWatch.ElapsedTicks;
        double 延迟 = 0;

        while (runThreadB)
        {
            if ((double)(stopWatch.ElapsedTicks - startTicks) / System.Diagnostics.Stopwatch.Frequency >= 延迟)
            {
                runThreadB = false;
                double preTicks = stopWatch.ElapsedTicks;

                Line3Double lineA = new Line3Double(new Vector3DoublePrecision(10, 20, 30), new Vector3DoublePrecision(100, 140, 180));
                Line3Double lineB = new Line3Double(new Vector3DoublePrecision(-10, -20, -30), new Vector3DoublePrecision(-100, -140, -180));

                int lines = 1000;

                for (int i = 0; i < 8; i++)
                {
                    for (int j = 0; j < lines; j++)
                    {
                        double aStartX = lineA.startX;
                        double aStartY = lineA.startY;
                        double aStartZ = lineA.startZ;

                        double aEndX = lineA.endX;
                        double aEndY = lineA.endY;
                        double aEndZ = lineA.endZ;

                        double aDirX = lineA.dirX;
                        double aDirY = lineA.dirY;
                        double aDirZ = lineA.dirZ;

                        double aDotSelf = lineA.dotSelf;

                        for (int k = 0; k < 8; k++)
                        {
                            for (int l = 0; l < lines; l++)
                            {
                                double wX = aStartX - lineB.startX;
                                double wY = aStartY - lineB.startY;
                                double wZ = aStartZ - lineB.startZ;

                                double b = aDirX * lineB.dirX + aDirY * lineB.dirY + aDirZ * lineB.dirZ;
                                double d = aDirX * wX + aDirY * wY + aDirZ * wZ;
                                double e = lineB.dirX * wX + lineB.dirY * wY + lineB.dirZ * wZ;

                                double D = aDotSelf * lineB.dotSelf - b * b;
                                double sc, tc;
                                if (D < 0.0000001)
                                {
                                    // the lines are almost parallel
                                    sc = 0.0f;
                                    tc = (b > lineB.dotSelf ? d / b : e / lineB.dotSelf);
                                }
                                else
                                {
                                    sc = (b * e - lineB.dotSelf * d) / D;
                                    tc = (aDotSelf * e - b * d) / D;
                                }

                                double shortestX = wX + (sc * aDirX) - (tc * lineB.dirX);
                                double shortestY = wY + (sc * aDirY) - (tc * lineB.dirY);
                                double shortestZ = wZ + (sc * aDirZ) - (tc * lineB.dirZ);

                                double 距离 = shortestX * shortestX + shortestY * shortestY + shortestZ * shortestZ;
                            }
                        }
                    }
                }

                double postTicks = stopWatch.ElapsedTicks;
                double time = ((postTicks - preTicks) / System.Diagnostics.Stopwatch.Frequency) * 1000;
                elapsedTimeB = time;
            }
        }
    }
}
public struct Vector3DoublePrecision
{
    public double x;
    public double y;
    public double z;

    public Vector3DoublePrecision(double x, double y, double z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }
}

public struct Line3Double
{
    public double startX;
    public double startY;
    public double startZ;
    public double endX;
    public double endY;
    public double endZ;

    public double dirX;
    public double dirY;
    public double dirZ;

    public double dotSelf;

    public Line3Double(Vector3DoublePrecision start, Vector3DoublePrecision end)
    {
        startX = start.x;
        startY = start.y;
        startZ = start.z;

        endX = end.x;
        endY = end.y;
        endZ = end.z;

        dirX = end.x - start.x;
        dirY = end.y - start.y;
        dirZ = end.z - start.z;

        dotSelf = dirX * dirX + dirY * dirY + dirZ * dirZ;
    }
}
 
Solution
感谢您的所有投入,尤其是感谢Skydiver对其进行了测试。你的低迷时期让我接受了更多"off"不仅仅是两个线程之间的编译差异。
因此,我真的深入研究了我的Unity项目的整个编译设置,并查看了我通常不会碰到的设置(不必,也不必关心),现在它已经成为Unity的特定问题,我可能以及谈论Unity特定的解决方案。因为找到了解决方案。还有一个主要的。
因此,在项目设置中>玩家可以在Mono和IL2CPP之间进行选择"scripting backend". Default is Mono.
这给了我这两个时间,也给了我两个线程之间的差异。
在A上为2.8秒
B上的0.6s

当改变...

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,497
地点
弗吉尼亚州切萨皮克
编程经验
10+
我没有看到太大的不同。
C#:
Thread A: 60.38267433430785
Thread B: 59.519296446894785

下面是我使用的代码。每当您进行计时时,请确保为发布进行编译:
C#:
using System;
using System.Threading;

public class ThreadTest
{
    Thread threadA;
    Thread threadB;

    bool runThreadA = false;
    bool runThreadB = false;

    System.Diagnostics.Stopwatch stopWatch;

    double elapsedTimeA = 0;
    double elapsedTimeB = 0;

    public (double, double) Run()
    {
        stopWatch = new System.Diagnostics.Stopwatch();
        StartThreads();
        threadA.Join();
        threadB.Join();
        return (elapsedTimeA, elapsedTimeB);
    }

    public void StartThreads()
    {
        stopWatch.Reset();
        stopWatch.Start();
        threadA = new Thread(ThreadA);
        threadB = new Thread(ThreadB);

        runThreadA = true;
        runThreadB = true;

        elapsedTimeA = 0;
        elapsedTimeB = 0;
        threadA.Start();
        threadB.Start();
    }

    void ThreadA()
    {
        while (runThreadA)
        {

            runThreadA = false;
            double preTicks = stopWatch.ElapsedTicks;

            Line3Double lineA = new Line3Double(new Vector3DoublePrecision(10, 20, 30), new Vector3DoublePrecision(100, 140, 180));
            Line3Double lineB = new Line3Double(new Vector3DoublePrecision(-10, -20, -30), new Vector3DoublePrecision(-100, -140, -180));

            int lines = 1000;

            for (int i = 0; i < 8; i++)
            {
                for (int j = 0; j < lines; j++)
                {
                    double aStartX = lineA.startX;
                    double aStartY = lineA.startY;
                    double aStartZ = lineA.startZ;

                    double aEndX = lineA.endX;
                    double aEndY = lineA.endY;
                    double aEndZ = lineA.endZ;

                    double aDirX = lineA.dirX;
                    double aDirY = lineA.dirY;
                    double aDirZ = lineA.dirZ;

                    double aDotSelf = lineA.dotSelf;

                    for (int k = 0; k < 8; k++)
                    {
                        for (int l = 0; l < lines; l++)
                        {
                            double wX = aStartX - lineB.startX;
                            double wY = aStartY - lineB.startY;
                            double wZ = aStartZ - lineB.startZ;

                            double b = aDirX * lineB.dirX + aDirY * lineB.dirY + aDirZ * lineB.dirZ;
                            double d = aDirX * wX + aDirY * wY + aDirZ * wZ;
                            double e = lineB.dirX * wX + lineB.dirY * wY + lineB.dirZ * wZ;

                            double D = aDotSelf * lineB.dotSelf - b * b;
                            double sc, tc;
                            if (D < 0.0000001)
                            {
                                // the lines are almost parallel
                                sc = 0.0f;
                                tc = (b > lineB.dotSelf ? d / b : e / lineB.dotSelf);
                            }
                            else
                            {
                                sc = (b * e - lineB.dotSelf * d) / D;
                                tc = (aDotSelf * e - b * d) / D;
                            }

                            double shortestX = wX + (sc * aDirX) - (tc * lineB.dirX);
                            double shortestY = wY + (sc * aDirY) - (tc * lineB.dirY);
                            double shortestZ = wZ + (sc * aDirZ) - (tc * lineB.dirZ);

                            double 距离 = shortestX * shortestX + shortestY * shortestY + shortestZ * shortestZ;
                        }
                    }
                }
            }

            double postTicks = stopWatch.ElapsedTicks;
            double time = ((postTicks - preTicks) / System.Diagnostics.Stopwatch.Frequency) * 1000;
            elapsedTimeA = time;
        }
    }

    void 线程B()
    {
        long startTicks = stopWatch.ElapsedTicks;
        double 延迟 = 0;

        while (runThreadB)
        {
            if ((double)(stopWatch.ElapsedTicks - startTicks) / System.Diagnostics.Stopwatch.Frequency >= 延迟)
            {
                runThreadB = false;
                double preTicks = stopWatch.ElapsedTicks;

                Line3Double lineA = new Line3Double(new Vector3DoublePrecision(10, 20, 30), new Vector3DoublePrecision(100, 140, 180));
                Line3Double lineB = new Line3Double(new Vector3DoublePrecision(-10, -20, -30), new Vector3DoublePrecision(-100, -140, -180));

                int lines = 1000;

                for (int i = 0; i < 8; i++)
                {
                    for (int j = 0; j < lines; j++)
                    {
                        double aStartX = lineA.startX;
                        double aStartY = lineA.startY;
                        double aStartZ = lineA.startZ;

                        double aEndX = lineA.endX;
                        double aEndY = lineA.endY;
                        double aEndZ = lineA.endZ;

                        double aDirX = lineA.dirX;
                        double aDirY = lineA.dirY;
                        double aDirZ = lineA.dirZ;

                        double aDotSelf = lineA.dotSelf;

                        for (int k = 0; k < 8; k++)
                        {
                            for (int l = 0; l < lines; l++)
                            {
                                double wX = aStartX - lineB.startX;
                                double wY = aStartY - lineB.startY;
                                double wZ = aStartZ - lineB.startZ;

                                double b = aDirX * lineB.dirX + aDirY * lineB.dirY + aDirZ * lineB.dirZ;
                                double d = aDirX * wX + aDirY * wY + aDirZ * wZ;
                                double e = lineB.dirX * wX + lineB.dirY * wY + lineB.dirZ * wZ;

                                double D = aDotSelf * lineB.dotSelf - b * b;
                                double sc, tc;
                                if (D < 0.0000001)
                                {
                                    // the lines are almost parallel
                                    sc = 0.0f;
                                    tc = (b > lineB.dotSelf ? d / b : e / lineB.dotSelf);
                                }
                                else
                                {
                                    sc = (b * e - lineB.dotSelf * d) / D;
                                    tc = (aDotSelf * e - b * d) / D;
                                }

                                double shortestX = wX + (sc * aDirX) - (tc * lineB.dirX);
                                double shortestY = wY + (sc * aDirY) - (tc * lineB.dirY);
                                double shortestZ = wZ + (sc * aDirZ) - (tc * lineB.dirZ);

                                double 距离 = shortestX * shortestX + shortestY * shortestY + shortestZ * shortestZ;
                            }
                        }
                    }
                }

                double postTicks = stopWatch.ElapsedTicks;
                double time = ((postTicks - preTicks) / System.Diagnostics.Stopwatch.Frequency) * 1000;
                elapsedTimeB = time;
            }
        }
    }
}
public struct Vector3DoublePrecision
{
    public double x;
    public double y;
    public double z;

    public Vector3DoublePrecision(double x, double y, double z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }
}

public struct Line3Double
{
    public double startX;
    public double startY;
    public double startZ;
    public double endX;
    public double endY;
    public double endZ;

    public double dirX;
    public double dirY;
    public double dirZ;

    public double dotSelf;

    public Line3Double(Vector3DoublePrecision start, Vector3DoublePrecision end)
    {
        startX = start.x;
        startY = start.y;
        startZ = start.z;

        endX = end.x;
        endY = end.y;
        endZ = end.z;

        dirX = end.x - start.x;
        dirY = end.y - start.y;
        dirZ = end.z - start.z;

        dotSelf = dirX * dirX + dirY * dirY + dirZ * dirZ;
    }
}

class Shell
{
    static void Main()
    {
        Console.WriteLine("Running...");
        var (a, b) = new ThreadTest().Run();
        Console.WriteLine($"Thread A: {a}");
        Console.WriteLine($"Thread B: {b}");
    }
}
 
已加入
2020年11月24日
留言内容
8
编程经验
10+
这是在Unity中运行的代码。因此,我不编译发行,我只是"Build the project" ;)

但这确实值得一提,因为我尚未构建它(只需直接在编辑器中进行测试)。但是当我这样做时,问题实际上会变得更大。
Unity构建时间:
线程A:8.77秒
线程B: 0.65 seconds

与已发布的代码相同。时间使用率再增加4倍。

似乎无论编译什么代码,最终都可以做得更好。
如果这在不同的环境中有所不同,那肯定会使调试变得更加困难。
知道如何处理吗?

感谢您的关注!
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,497
地点
弗吉尼亚州切萨皮克
编程经验
10+
因此,在第二篇文章中,我必须添加代码以确保在读取线程中设置的经过时间变量之前,两个线程均已完成。您确定要等待第二个线程完成之后再花时间吗?
 
已加入
2020年11月24日
留言内容
8
编程经验
10+
因此,在第二篇文章中,我必须添加代码以确保在读取线程中设置的经过时间变量之前,两个线程均已完成。您确定要等待第二个线程完成之后再花时间吗?
:) 否则,我也猜我的结果将为0。因为两个double值的保持时间要么为0,要么为实际结果。
我为该论坛准备的代码不太受Unity约束,在此过程中,我删除了提取结果的方法。
由于要花费时间(物理上是几秒钟的时间),我不仅将结果依赖于值,而且还依赖于与ThreadA相比ThreadB完成的速度。我必须亲自等待结果出来。
看来您的计算机的执行速度也比我的整体快,因为两个线程均在60毫秒内完成。在我的身上实际上需要一个"felt" amount of time...
 

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,497
地点
弗吉尼亚州切萨皮克
编程经验
10+
请注意,我测试过的机器是2010年左右制造的,当时是一台中型游戏机。
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,923
地点
英国
编程经验
10+
移至第三方产品论坛。
 

纳皮沃

游戏成瘾者
已加入
2020年10月17日
留言内容
8
地点
比利时(GMT + 1)
编程经验
1-3
I am pretty sure unity doesn't like multi threading as it is already pretty multi threaded itself and relies a lot on 折射.

过去,构建统一的复杂系统时,我为此目的创建了外部Dll,以便仅调用它们就不会破坏它们。

由于我的计算机决定内爆,因此我无法测试您的代码,至少在接下来的一两个星期内,我将没有代码。

在这种情况下,我发现有用的策略之一是独立测试每一侧的速度...然后查看它们可能在哪里阻塞彼此。

我看了一下代码,乍看没有发现任何错误。
 
已加入
2020年11月24日
留言内容
8
编程经验
10+
请注意,我测试过的机器是2010年左右制造的,当时是一台中型游戏机。
我的计算机是全新的18核Intel i9处理器。因此,如果您可以让它在60毫秒内运行这些线程,而我的时间是从600毫秒开始,那显然是错误的。
循环应获得运行64,000,000次的实际计算。您确定您的旧计算机应该能够在60毫秒内完成此操作吗?
也许我已经习惯了低性能,因为Unity使我的所有代码运行缓慢。我根本没有足够的书呆子来判断这样的事情。

编辑:可能是由于您的编译器只是剥离了整个计算,"distance"计算永远不会离开范围?我不知道有多少编译器会做优化,但是"distance"计算并没有真正用于任何事情,在现实世界中,最好让编译器从最终的机器代码中剥离掉这些无意义的东西。对?
 
Last edited:
已加入
2020年11月24日
留言内容
8
编程经验
10+
I am pretty sure unity doesn't like multi threading as it is already pretty multi threaded itself and relies a lot on 折射.

过去,构建统一的复杂系统时,我为此目的创建了外部Dll,以便仅调用它们就不会破坏它们。

由于我的计算机决定内爆,因此我无法测试您的代码,至少在接下来的一两个星期内,我将没有代码。

在这种情况下,我发现有用的策略之一是独立测试每一侧的速度...然后查看它们可能在哪里阻塞彼此。

我看了一下代码,乍看没有发现任何错误。
我也不知道"refraction"意思是(嗯,我确实知道这个词,以及它与电波在材料之间过渡的方式有何关系 ;))。但这听起来像您知道的东西。我从来没有想到过Unity会遇到类似的问题,因为在我的脑海中,Unity只处理自己的API,以及我们如何与之交互,而不涉及一般的编译或执行更通用的代码。但是,正如已经说过的,我根本不是一个很低级的技巧。
 

羊皮

退休程序员
工作人员
已加入
2018年9月5日
留言内容
1,923
地点
英国
编程经验
10+
我完全不认为这与Unity有关。现在我不太确定。
您的项目决定了它完全属于哪个论坛。由于您的代码和报告的问题与统一线程和统一线程有关,而不仅仅是c#,因此,您的问题严格来说并不是c#问题。将其移到此处并不意味着我们无法为您提供帮助。

如果有时间,我会稍后再尝试研究,因为我是该面板afaik上唯一的统一开发人员。您应该注意,但是unity不需要它自己的线程类,那么为什么您觉得需要添加它呢?

我的工作时间很长,所以可能要花很长时间才能重新审视此主题。
 
已加入
2020年11月24日
留言内容
8
编程经验
10+
您应该注意,但是unity不需要它自己的线程类,那么为什么您觉得需要添加它呢?

这不是"Unity线程类"。这是标准线程(System.Threading)。
我需要它,因为我需要一些不在Unity主线程中运行的计算。有些东西可能更重,因此无法在Unity的标准帧时间内执行。
所以除非我希望游戏能够"stutter",那么我需要在单独的线程中执行此操作。并且除非我在每个帧中都需要一些结果,否则没有理由尝试在一个帧中进行操作。这样我就不会伤害我的帧速率。
 
Last edited:

跳伞

工作人员
已加入
2019年4月6日
留言内容
2,497
地点
弗吉尼亚州切萨皮克
编程经验
10+
我将代码分别从ThreadA()和ThreadB()保存到a.cs和b.cs中,然后运行git diff -w a.cs b.cs来尝试查看两者之间的区别。这是出来的结果:
C#:
diff --git a/a.cs b/b.cs
index fa46078..449d9ed 100644
--- a/a.cs
+++ b/b.cs
@@ -1,9 +1,13 @@
-    void ThreadA()
-    {
-        while (runThreadA)
+    void 线程B()
     {
+        long startTicks = stopWatch.ElapsedTicks;
+        double 延迟 = 0;

-            runThreadA = false;
+        while (runThreadB)
+        {
+            if ((double)(stopWatch.ElapsedTicks - startTicks) / System.Diagnostics.Stopwatch.Frequency >= 延迟)
+            {
+                runThreadB = false;
                 double preTicks = stopWatch.ElapsedTicks;

                 Line3Double lineA = new Line3Double(new Vector3DoublePrecision(10, 20, 30), new Vector3DoublePrecision(100, 140, 180));
@@ -67,6 +71,7 @@

                 double postTicks = stopWatch.ElapsedTicks;
                 double time = ((postTicks - preTicks) / System.Diagnostics.Stopwatch.Frequency) * 1000;
-            elapsedTimeA = time;
+                elapsedTimeB = time;
+            }
         }
     }

So essentially the only difference between ThreadA() and 线程B() is:
C#:
while (runThreadA)
{
    runThreadA = false;

C#:
long startTicks = stopWatch.ElapsedTicks;
double 延迟 = 0;

while (runThreadB)
{
    if ((double)(stopWatch.ElapsedTicks - startTicks) / System.Diagnostics.Stopwatch.Frequency >= 延迟)
    {
        runThreadB = false;

Since the 延迟 is zero, then the condition in the if statement should always be true (unless the elapsed number of ticks wraps around back to zero between the time it took to set the value startTicks and the time takes to execute the check in the if-statement. But that wrap around case should result in Thread B taking 更长 比线程A多,这不是您看到的结果,线程A比线程B花更长的时间。

在这一点上,我现在只能想到两件事:
1)您正在测试速度的代码不是您在此处发布以供我们试用的代码。
2)在Unity上进行JIT(Just-In-Time)编译所花费的时间非常慢,并且当前线程A为执行JIT操作付出了代价。
 
已加入
2020年11月24日
留言内容
8
编程经验
10+
感谢您的所有投入,尤其是感谢Skydiver对其进行了测试。你的低迷时期让我接受了更多"off"不仅仅是两个线程之间的编译差异。
因此,我真的深入研究了我的Unity项目的整个编译设置,并查看了我通常不会碰到的设置(不必,也不必关心),现在它已经成为Unity的特定问题,我可能以及谈论Unity特定的解决方案。因为找到了解决方案。还有一个主要的。
因此,在项目设置中>玩家可以在Mono和IL2CPP之间进行选择"scripting backend". Default is Mono.
这给了我这两个时间,也给了我两个线程之间的差异。
在A上为2.8秒
B上的0.6s

当更改为IL2CPP时,
A和B均为0.000001s

Now... that was too little I 毡. So I took all the 距离 calculations, and actually put them to use by summing two global variables with the results. I feared compilation got rid of the calculation due to the result never leaving the threads.
现在?

A:0.15秒
B:0.149秒

换句话说:准时的重大改进,而最重要的是?他们现在一样!
所以。再次感谢。您的反馈迫使我改变了我通常不接触的东西,这在性能和可靠性上都产生了巨大的变化。
可以认为该线程已解决。不仅如此……我可以算是进步了! ;)
谢谢...
 
最佳 底部