我有以下功能:
public void scanText(char[] T){
int q=0;
for(int i=0;i<T.length;i++){
q = transFunc[preCompRow[q]+T[i]];
if(q==pattern.length){
System.out.println("match found at position: "+(i-pattern.length+2));
}
}
}
此函数扫描char数组,搜索给定模式的匹配项,该模式存储为有限自动机。自动机的转换函数存储在名为transFunc的变量中。
我正在使用800万个字符并使用800000个模式的文本中测试此功能。事情是数组preCompRow [q](这是一个int [])的加入非常慢。如果我删除代码的preCompRow [q],性能会大大提高。我认为这可能是因为在每个循环中,q变量具有不同的非顺序值(2,56,18,9 ......)。
有没有更好的方法以非顺序方式访问数组?
提前致谢!
答案 0 :(得分:1)
一种可能的解释是,由于内存访问模式的位置不佳,您的代码会看到内存性能不佳。
现代计算机中内存缓存的作用是处理处理器指令时间(小于1 ns)和主内存(5到10 ns或更长)之间的速度不匹配。当代码在从内存中获取的大部分时间内获得缓存时,它们的效果最佳。
现代英特尔芯片组以64字节为单位缓存内存,并以突发模式从主内存加载。 (这相当于16个int
值。)(比如说)I7处理器上的L1缓存是2MB。
如果您的应用程序能够按顺序(大致)按顺序访问大型数组中的数据,则8次访问中的7次将是缓存命中。如果访问模式是非顺序的并且“工作集”是高速缓存大小的大倍,那么最终可能会在每次内存访问时出现高速缓存未命中。
如果内存访问位置是yoiur问题的根源,那么您的选项是有限的:
重新编码现有的C或C ++可能会提高性能,但同样的内存位置问题也会让你感到困扰。
我不知道有任何工具可用于衡量Java应用程序中的缓存性能。