我写了一个小程序来比较笔记本电脑的性能。为了使程序CPU密集,我实现了Rabin-Karp模式匹配算法和一些多线程代码(通过Parallel API实现)。
我注意到,当关闭编译器优化标志执行程序时,所需的时间比打开优化标志所需的时间要多得多。
例如:
我很想知道编译器正在采用什么样的优化来增加性能的显着改进。在打开/关闭此标志的情况下执行代码时,任何关于如何理解的指针都将非常有用。
代码
void Main()
{
Dictionary<string,bool> collection = new Dictionary<string,bool>();
IEnumerable<string> commonWords = File.ReadAllLines(@"G:\LINQPad4\words.txt")
.Where(x => !string.IsNullOrEmpty(x)).Select(t => t.Trim());
string magna_carta = File.ReadAllText(@"G:\LINQPad4\magna-carta.txt");
Parallel.ForEach(commonWords,
() => new Dictionary<string,bool>(),
(word, loopState, localState) =>
{
RabinKarpAlgo rbAlgo = new RabinKarpAlgo(magna_carta,word);
localState.Add(word,rbAlgo.Match());
return localState;
},
(localState) =>
{
lock(collection){
foreach(var item in localState)
{
collection.Add(item.Key, item.Value);
}
}
});
collection.Dump();
}
public class RabinKarpAlgo
{
private readonly string inputString;
private readonly string pattern;
private ulong siga = 0;
private ulong sigb = 0;
private readonly ulong Q = 100007;
private readonly ulong D = 256;
public RabinKarpAlgo(string inputString, string pattern)
{
this.inputString = inputString;
this.pattern = pattern;
}
public bool Match()
{
for (int i = 0; i < pattern.Length; i++)
{
siga = (siga * D + (ulong)inputString[i]) % Q;
sigb = (sigb * D + (ulong)pattern[i]) % Q;
}
if(siga == sigb)
return true;
ulong pow = 1;
for (int k = 1; k <= pattern.Length - 1; k++)
pow = (pow * D) % Q;
for (int j = 1; j <= inputString.Length - pattern.Length; j++)
{
siga = (siga + Q - pow * (ulong)inputString[j - 1] %Q) % Q;
siga = (siga * D + (ulong)inputString[j + pattern.Length - 1]) % Q;
if (siga == sigb)
{
if (inputString.Substring(j, pattern.Length) == pattern)
{
return true;
}
}
}
return false;
}
}
您可以从以下gitHub存储库下载相关文件:Rabin-Karp Test
答案 0 :(得分:3)
在你的特殊情况下,有3个for循环,它们位于一个平行的foreach中, 我坚信大多数优化都是通过动态循环转换完成的,当然还有数学部分。
以下是一些可以通过循环完成的示例:Loop transformation
来自C#编译器团队的Eric Lippert有一篇关于此的博客文章: what does the optimize switch do