C# 需要加快锯齿阵列中的模式匹配
我有一个锯齿阵列,20乘20。我尝试匹配700种不同的模式,这些模式构建得像较小的锯齿状阵列。匹配的值(字节或:ed在一起)可以是“player”、“对手”、“empty”或“don't care”,也可以是这些值的组合。图案大小从4x4到7x7不等 我怎样才能加快速度?我相信有更好的方法可以做到这一点。现在,检查所有模式大约需要一秒钟的时间。我需要知道所有的匹配项,而不是每个模式一次C# 需要加快锯齿阵列中的模式匹配,c#,unity3d,pattern-matching,jagged-arrays,C#,Unity3d,Pattern Matching,Jagged Arrays,我有一个锯齿阵列,20乘20。我尝试匹配700种不同的模式,这些模式构建得像较小的锯齿状阵列。匹配的值(字节或:ed在一起)可以是“player”、“对手”、“empty”或“don't care”,也可以是这些值的组合。图案大小从4x4到7x7不等 我怎样才能加快速度?我相信有更好的方法可以做到这一点。现在,检查所有模式大约需要一秒钟的时间。我需要知道所有的匹配项,而不是每个模式一次 // Iterate through all patterns for( int patNum = 0; pa
// Iterate through all patterns
for( int patNum = 0; patNum < whitePatterns.Length; patNum++)
{
// Get current pattern
pat = whitePatterns[patNum];
col = pat.pattern.Length;
row = pat.pattern[0].Length;
for (int x = 0; x < myBoard.Size - col + 1; ++x)
{
for (int y = 0; y < myBoard.Size - row + 1; ++y)
{
for (int xx = 0; xx < col; ++xx)
for (int yy = 0; yy < row; ++yy)
{
count++;
if ((myBoard.board[x + xx][y + yy] & pat.pattern[xx][yy]) == 0)
{
goto loopY;
}
}
// Found a match!
loopY: ;
}
}
}
//遍历所有模式
for(int patNum=0;patNum
有时候暴力是最好的方法。但是,您不太可能利用您的CPU。作为一个非常基本的开始,使用并行化来充分利用机器的处理能力
Parallel.ForEach(whitePatterns, wp =>
{
int col = wp.pattern.Length;
int row = wp.pattern[0].Length;
for (int x = 0; x < myBoard.Size - col + 1; ++x)
{
for (int y = 0; y < myBoard.Size - row + 1; ++y)
{
for (int xx = 0; xx < col; ++xx)
for (int yy = 0; yy < row; ++yy)
{
count++;
if ((myBoard.board[x + xx][y + yy] & wp.pattern[xx][yy]) == 0)
{
goto loopY;
}
}
// Found a match!
loopY: ;
}
}
});
Parallel.ForEach(whitePatterns,wp=>
{
int col=wp.pattern.Length;
int row=wp.pattern[0]。长度;
对于(int x=0;x
因此,您有一组固定的模式,并且希望在游戏板上搜索所有出现的模式
这听起来很可疑,就像有一组固定的搜索字符串,您希望在大量文本中查找这些字符串
我并不是说这很容易,但是你可以从固定的模式集合中构建一个状态机,然后在它上面运行一个经过修改的Aho-Corasick算法
实际上,您要做的是将每个模式的每一行都视为一个“字符串”,然后根据这些模式构建Aho-Corasick树结构。然后,在整个游戏板中查找所有匹配的字符串。您的结果将是一组模式行及其起始地址(行、列)和模式编号
按模式编号、行编号(即模式中的行编号)、起始列和起始行对这些结果进行排序。然后,您可以按顺序浏览已排序的列表并选择匹配的模式。如果模式的第一行开始于游戏板位置(行,列),下一行开始于游戏板位置(行+1,列),则模式匹配
生成状态机需要一些(少量)时间,但您只需执行一次。在那之后,搜索速度惊人地快。对结果进行排序并找出匹配项将非常快
我用C#构建了一个Aho-Corasick模式匹配器,它可能会帮助您开始。请参阅我的文章。您是否尝试过用Parallel.ForEach()替换模式迭代器?暴力攻击没有神奇的解决方法。但它似乎非常适合并行化。你可以使用4x4组合的字典。这将使全部或部分查找非常快速,但是创建这样的字典并提供查找将增加复杂性并需要一些时间。我使用的Unity使用Mono 2.6,看起来它不支持Parallel.ForEach。将找到一种尝试并行化模式循环的方法。根据要做的工作量,您可能希望更改
for
的并行。ForEach
或Parallel.for
。对于700个测试项目来说,这个答案可能是正确的。我强烈建议您查看Microsoft“”提供的免费书籍。特别是查看反模式“太细粒度,太粗粒度”,以了解更多关于为循环并行嵌套的。@ScottChamberlain对此表示感谢。我以前从未遇到过这种情况。我真的会喜欢这本书的。:-)使用不支持Parallel.ForEach的Unity。我将检查如何在Unity中实现它。嗨,Jon,我不确定你是否得到了这个,我发现了一个与.NET3.5兼容的版本。这是一个并行程序。例如,当迭代whitepatterns的长度并打印索引时,它就像一个符咒,但是如果我在上面的代码中尝试它,我会得到一个超出范围的数组。有什么线索能导致这种情况吗?我需要某种密码锁吗?@Andreas太好了。你不需要锁。当数组超出边界时,在某个地方生成的数字超出了一个数组的范围,但是如果没有完整的代码,我无法确定在哪里。我只能建议您在Parallel.For循环之外放置一些全局变量来捕获col、row、x、y、xx和wp。然后并行包装。对于每个循环,在一次尝试中,将当前变量的值写入全局变量,在异常点设置断点,全局变量会让您了解其失败的原因。感谢您的建议,我将阅读您的文章。这需要对模式进行一些处理,但最终可能是值得的:)