关键词:PCIe-PXIe-68565、工控机
1.问题描述
本期KB总结了一些在使用C#编程时能够提高效率的算法优化。
2.优化的算法
下面介绍几个常用的算法优化方法,并使用StopWatch对优化前后的效率进行对比。
1. 使用ref关键字或其他in - place方法,直接对输入数组进行操作
static int[] AddOne_Outplace()
{
int[] array = { 12, 5, 8, 4, 3 };
for (int i = 0; i < array.Length ; i++)
{
array[i]++;
}
return array;
}
static void AddOne_Inplace(ref int[] array)
{
for (int i = 0; i < array.Length; i++)
{
array[i]++;
}
}
private static void Main(string[] args)
{
Stopwatch sw = Stopwatch.StartNew();
int[] a;
for (int i = 0; i < 100000; i++)
{
a = AddOne_Outplace();
}
Console.WriteLine(sw.ElapsedMilliseconds);
sw.Restart();
int[] array = { 12, 5, 8, 4, 3 };
for (int i = 0; i < 100000; i++)
{
AddOne_Inplace(ref array);
}
Console.WriteLine(sw.ElapsedMilliseconds);
Console.Read();
}
图 1 使用In-place方法前后效率对比
2. 对比较简单的循环使用循环展开的方法
int length = 50000000;
double[] a = new double[length];
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < length; i++)
{
a[i]++;
}
Console.WriteLine(sw.ElapsedMilliseconds);
sw.Restart();
for (int i = 0; i < length; i += 4)
{
a[i]++;
a[i + 1]++;
a[i + 2]++;
a[i + 3]++;
}
Console.WriteLine(sw.ElapsedMilliseconds);
Console.Read();
图 2 使用循环展开前后效率对比
3. 所有涉及到数学计算级联方法的调用都放到一个for循环中进行
int length = 50000000;
double a=1, b=2;
double[] c = new double[length];
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < length; i++)
{
c[i] = b * 2;
}
for (int i = 0; i < length; i++)
{
c[i] =c[i]+a;
}
Console.WriteLine(sw.ElapsedMilliseconds);
sw.Restart();
for (int i = 0; i < length; i++)
{
c[i] = a + b * 2;
}
Console.WriteLine(sw.ElapsedMilliseconds);
Console.Read();
图 3 数学级联方法调用优化前后效率对比
4. 将Linq语句都替换为for循环
int length = 5000000;
double[] a = new double[length];
Stopwatch sw = Stopwatch.StartNew();
double[] b = a.Select(x => x++).ToArray();
Console.WriteLine(sw.ElapsedMilliseconds);
sw.Restart();
for (int i = 0; i < length; i++)
{
a[i]++;
}
Console.WriteLine(sw.ElapsedMilliseconds);
Console.Read();
图 4 Ling语句与for循环效率对比
5. 检查循环中的值类型与引用类型之间的转换,减少拆箱和装箱
string a;
string b;
string c;
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 5000000; i++)
{
a = 1.ToString();
b = 2.ToString();
c = a + ""+b;
}
Console.WriteLine(sw.ElapsedMilliseconds);
sw.Restart();
a = 1.ToString();
b = 2.ToString();
for (int i = 0; i < 5000000; i++)
{
c = a + "" + b;
}
Console.WriteLine(sw.ElapsedMilliseconds);
Console.Read();
图 5 减少装箱前后效率对比
6. 嵌套的for循环,当数组较大时,索引终值为常量可以缩短执行时间
int[] data = new int[100000000];
const int a = 100000000;//常量
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < data.Length; i++)
{
data[i] = i;
}
Console.WriteLine(sw.ElapsedMilliseconds);
sw.Restart();
for (int i = 0; i < a; i++)
{
data[i] = i;
}
Console.WriteLine(sw.ElapsedMilliseconds);
图 6 for循环索引终值为变量和常量的对比
Console.Read();
7. Array类的静态方法效率很高,比如Array.Copy方法快于List的AddRange,后者又快于Linq语句的Concat方法。
int length = 5000000;
double[] a = new double[length];
double[] b = new double[length];
double[] c = new double[length * 2];
Random rd = new Random();
for (int i = 0; i < length; i++)
{
a[i] = rd.NextDouble();
b[i] = rd.NextDouble();
}
Stopwatch sw = Stopwatch.StartNew();
c = a.Concat(b).ToArray();
Console.WriteLine(sw.ElapsedMilliseconds);
sw.Restart();
List<double> list = new List<double>();
list.AddRange(a);
list.AddRange(b);
Console.WriteLine(sw.ElapsedMilliseconds);
sw.Restart();
Array.Copy(a, 0, c, 0, length);
Array.Copy(b, 0, c, length, length);
Console.WriteLine(sw.ElapsedMilliseconds);
图 7 Linq方法,List方法,Array方法效率对比
Console.Read();
Copyright © 2016-2025 JYTEK All Rights Reserved.