加速c#循环
本文关键字:循环 加速 | 更新日期: 2023-09-27 18:16:04
我正试图找到一种快速的方法来加速以下for loops
。(只是有趣的理论东西)
我有以下程序
using System;
using System.Collections;
using System.Diagnostics;
namespace SpeedTest
{
class Program
{
static void Main(string[] args)
{
Stopwatch timer = new Stopwatch();
timer.Start();
ArrayList widgets = new ArrayList(50000);
for (int i = 0; i < widgets.Capacity; i++)
{
widgets.Add(new Widget(i));
}
string ProcessingMessages = "";
for (int i = 0; i < widgets.Count; i++)
{
Widget widgetToProcess = (Widget)widgets[i];
ProcessingMessages += widgetToProcess.ProcessWidget();
ProcessingMessages += "'r'n";
}
Console.WriteLine(ProcessingMessages);
timer.Stop();
Console.WriteLine(timer.Elapsed);
Console.ReadLine();
}
}
class Widget
{
public Widget()
{
this.CreatedDateTime = DateTime.Now;
}
public Widget(int ID) : this()
{
this.ID = ID;
}
public DateTime CreatedDateTime { get; set; }
public int ID { get; set; }
public string ProcessWidget()
{
int Z = this.ID + this.ID;
string Message = "Widget ID " + this.ID;
Message += " was created on ";
Message += CreatedDateTime.Year + "-" + CreatedDateTime.Month + "-" + CreatedDateTime.Day + ", at ";
Message += CreatedDateTime.Hour + ":" + CreatedDateTime.Minute + ", with a value of ";
Message += Z.ToString();
return Message;
}
}
}
我如何加速这些for loops
本身?我知道实现并行会很有用,比如
for (int i = 0; i < widgets.Count; i += 10)
{
Widget widgetToProcess1 = (Widget)widgets[i];
Widget widgetToProcess2 = (Widget)widgets[i+1];
Widget widgetToProcess3 = (Widget)widgets[i+2];
Widget widgetToProcess4 = (Widget)widgets[i+3];
Widget widgetToProcess5 = (Widget)widgets[i+4];
Widget widgetToProcess6 = (Widget)widgets[i + 5];
Widget widgetToProcess7 = (Widget)widgets[i + 6];
Widget widgetToProcess8 = (Widget)widgets[i + 7];
Widget widgetToProcess9 = (Widget)widgets[i + 8];
Widget widgetToProcess10 = (Widget)widgets[i + 9];
ProcessingMessages += widgetToProcess1.ProcessWidget() + "'r'n" +
widgetToProcess2.ProcessWidget() + "'r'n" +
widgetToProcess3.ProcessWidget() + "'r'n" +
widgetToProcess4.ProcessWidget() + "'r'n" +
widgetToProcess5.ProcessWidget() + "'r'n" +
widgetToProcess6.ProcessWidget() + "'r'n" +
widgetToProcess7.ProcessWidget() + "'r'n" +
widgetToProcess8.ProcessWidget() + "'r'n" +
widgetToProcess9.ProcessWidget() + "'r'n" +
widgetToProcess10.ProcessWidget() + "'r'n";
}
但是这些都是手工写的。我正试图找到一种方法来动态分解一个大的任务/数组大小和运行这些块更快。
寻找一些简单的想法/概念。或者,是否有比使用for
环路更好的替代方案。
对于初学者来说,你在一个紧密的循环中做字符串连接-不好,看看StringBuilder。
其次,您要在您的时间安排中包括设置您的测试场景。
第三,不清楚处理for循环的成本与ProcessWidget()
方法的成本之间的相对成本。当然,任何优化将发生在这个方法内?
向下滚动查看ProcessWidget()
方法,您还可以从删除所有字符串连接并替换为一个大的string.Format()
调用或使用StringBuilder
中受益。此外,ID和CreatedDateTime看起来像不可变的字段,也许值得将它们定义为readonly
并在构造函数中预先创建字符串描述(如果ProcessWidget()可能被多次调用)。
您也可以考虑使用:
widgets.Cast<Widget>().AsParallel().ForAll(widgetToProcess => {...});
这将提高您的进程的性能,从超过4分钟到不到30秒(取决于CPU配置)。
可以通过以下方式提高总体速度:使用StringBuilder并将控制台输出移到ProcessWidget调用中,然后将数组填充和处理放入Parallel中。为总运行时间为~7秒
修改后的代码:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.Diagnostics;
namespace parallelFor
{
class Program
{
static void Main(string[] args)
{
Stopwatch timer = new Stopwatch();
timer.Start();
int size = 50000;
ArrayList widgets = new ArrayList(size);
Parallel.For(0, size, i =>
{
Widget w = new Widget((int)i);
widgets.Add(w);
w.ProcessWidget();
});
timer.Stop();
Console.WriteLine(timer.Elapsed);
Console.ReadLine();
}
}
class Widget
{
public Widget()
{
this.CreatedDateTime = DateTime.Now;
}
public Widget(int ID)
: this()
{
this.ID = ID;
}
public DateTime CreatedDateTime { get; set; }
public int ID { get; set; }
public void ProcessWidget()
{
int Z = this.ID + this.ID;
string Message = "Widget ID " + this.ID;
Message += " was created on ";
Message += CreatedDateTime.Year + "-" + CreatedDateTime.Month + "-" + CreatedDateTime.Day + ", at ";
Message += CreatedDateTime.Hour + ":" + CreatedDateTime.Minute + ", with a value of ";
Message += Z.ToString();
Console.WriteLine(Message);
}
}
}