手动编码的循环比建议的 Linq 替代方案快得多。请参阅下面的更新 2。
一种或另一种方式,您将遍历数组的每个元素来回答您的问题,因为没有为数组指定排序。
您的代码就是这样做的,隐藏了循环的实现。使用 Linq 执行循环至少比编写自己的for
循环慢一点,因为它做的工作更多。(实际上,由于您没有缓存 的结果,因此您此时会遍历数组两次myArray.Cast<double>().Min()
)。
对于大多数处理器,您应该按行主要顺序遍历循环,因为它遍历相邻的内存地址(在我自己的测试中,以错误的顺序遍历可能会慢 30%)。
如果实际上数组中的值有某种顺序,则可能会进行更有效的搜索。
更新
我怀疑手动编码的循环会比使用 Linq 快得多,因为循环体是微不足道的。如果最后一点性能都很重要,我建议您同时实现选项和基准测试。
Reed 的并行运行建议也值得进行基准测试。您可以使用Parallel.For非常轻松地并行化传统迭代。
更新 2
测量了 Reed 解决方案和手动编码循环的性能。
Linq:1448.6353 毫秒
For 循环:125.2208 毫秒
使用的代码:
class Program
{
const int SIZE = 3000;
static double[,] data = new double[SIZE,SIZE];
static void Main(string[] args)
{
if (args.Length >= 1 && args[0] == "/for")
{
Benchmark(ForLoop);
}
else
{
Benchmark(LinqLoop);
}
}
static void ForLoop()
{
for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
{
if (double.IsNaN(data[i, j]) || double.IsInfinity(data[i, j])) Console.WriteLine("FOUND!");
}
}
}
static void LinqLoop()
{
if (!data.Cast<double>().Any(d => double.IsNaN(d) || double.IsInfinity(d))) Console.WriteLine("FOUND!");
}
static void Benchmark(Action a)
{
Stopwatch watch = Stopwatch.StartNew();
a();
TimeSpan span = watch.Elapsed;
Console.WriteLine("Milliseconds: " + span.TotalMilliseconds + " ms");
Console.ReadKey();
}
}