gpt4 book ai didi

c# - 以这种方式使用时,内联 if 语句是否有效?

转载 作者:行者123 更新时间:2023-11-30 13:15:01 25 4
gpt4 key购买 nike

如果我给一个变量赋值,然后想给它赋第二个值,但前提是它满足条件,使用简写 if 语句是否同样有效?这是一个例子。

这样效率更高吗

int x = GetInt();
if (x < 5)
x = 5;

比这个

int x = GetInt();
x = x < 5 ? 5 : x;

我想我真正想问的是,如果 x 不满足条件,那么 else 语句中的 x = x 会影响性能吗?

最佳答案

我喜欢这个版本:

int x = Math.Max(5, GetInt());

但请记住,所有这些都是不成熟的优化。今天更快的东西明天可能会更慢,因为像 Windows 更新这样简单的东西会更改框架以添加新的或不同的 JIT 优化。

我可能会花一些时间看看你是否在一个大循环中运行这样的检查:

 var items = Enumerable.Range(0, 1000000);

foreach(int item in items)
{
if (item % 3 == 0)
{
//...
}
else
{
//...
}
}

检查循环的原因主要不是因为代码会尽可能快地运行很多次,更强调小的效率低下,而是因为无论你使用 if 还是else 在整个循环中来回变化。

我预计该代码效率低下,因为现代 CPU 的一项功能称为分支预测。如果 ifelse 的内容足够重要并且足够不同,您可以通过移动执行所有操作使该代码运行得更快很多这些检查(并将所有预测都失败)放在前端,然后一起运行所有 if,然后运行所有 else。它会更快,因为运行 if 和 else 的第二阶段的分支预测(运行起来可能要昂贵得多)会更准确。

下面是一个演示差异的小程序:

class Program
{
static int samplesize = 1000000;
//ensure these are big enough that we don't spend time allocating new buffers while the stopwatch is running
static Dictionary<int, string> ints = new Dictionary<int,string>(samplesize * 4);
static Dictionary<double,string> doubles = new Dictionary<double,string>(samplesize * 4);

static void Main(string[] args)
{
var items = Enumerable.Range(0, samplesize).ToArray() ;
var clock = new Stopwatch();

test1(items); //jit hit, discard first run. Also ensure all keys already exist in the dictionary for both tests
clock.Restart();
test1(items);
clock.Stop();
Console.WriteLine("Time for naive unsorted: " + clock.ElapsedTicks.ToString());

test2(items); //jit hit
clock.Restart();
test2(items);
clock.Stop();
Console.WriteLine("Time for separated/branch prediction friendly: " + clock.ElapsedTicks.ToString());

Console.ReadKey(true);
}

static void test1(IEnumerable<int> items)
{
foreach(int item in items)
{
//different code branches that still do significant work in the cpu
// doing more work here results in a larger branch-prediction win, to a point
if (item % 3 == 0)
{ //force hash computation and multiplication op (both cpu-bound)
ints[item] = (item * 2).ToString();
}
else
{
doubles[(double)item] = (item * 3).ToString();
}
}
}

static void test2(IEnumerable<int> items)
{
//doing MORE work: need to evaluate our items two ways, allocate arrays
var intItems = items.Where(i => i % 3 == 0).ToArray();
var doubleItems = items.Where(i => i % 3 != 0).ToArray();

// but now there is no branching... adding all the ints, then adding all the doubles.
foreach (var item in intItems) { ints[item] = (item * 2).ToString(); }
foreach (var item in doubleItems) { doubles[(double)item] = (item * 3).ToString(); }
}
}

在我的机器上的结果是第二个测试,它做更多的工作,运行得更快:

Time for naive unsorted: 1118652
Time for separated/branch prediction friendly: 1005190

这里要带走的重要一点是,不是您需要回头看看是否所有循环都可以从分支预测中获益。这只是众多 CPU 功能中的一个,可以使性能结果让您大吃一惊。这里要带走的重要一点是,要确定代码将如何执行,您实际上需要衡量您的性能。如果您不仔细构建它,那么幼稚的技术仍然可以获胜(我的第一次尝试没有达到我预期的速度)。

此外,我需要指出的是,在这些情况下并没有太大区别。这种性能提升是否值得,或者您将时间花在其他地方会做得更好吗?了解这一点的唯一方法是实际衡量应用程序的整体性能,并找出它真正花费时间的地方。哪里真的比应该的慢?这称为分析,并且有一些工具可以帮助您准确地做到这一点。

关于c# - 以这种方式使用时,内联 if 语句是否有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16838733/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com