Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/369.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JAVA中int数组上非顺序迭代的低性能_Java_Arrays_Performance - Fatal编程技术网

JAVA中int数组上非顺序迭代的低性能

JAVA中int数组上非顺序迭代的低性能,java,arrays,performance,Java,Arrays,Performance,我有以下功能: 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));

我有以下功能:

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));
        }
    }
}
public void扫描文本(char[]T){
int q=0;

对于(inti=0;i一种可能的解释是,由于内存访问模式的局部性差,代码的内存性能很差

在现代计算机中,内存缓存的作用是处理处理器指令时间(小于1ns)和主内存(5到10ns或更多)之间的速度不匹配。当代码从内存中获取的缓存命中率最高时,它们工作得最好

现代Intel芯片组以64字节的块缓存内存,并以突发模式从主存加载(对应于16
int
值)。I7处理器上的一级缓存为2MB

如果您的应用程序能够按顺序(大致)访问大型阵列中的数据,则8次访问中有7次是缓存命中。如果访问模式是非顺序的,并且的“工作集”是缓存大小的大倍数,则每次内存访问都可能会导致缓存未命中

如果内存访问区域性是yoiur问题的根源,那么您的选择是有限的:

  • 重新设计算法,使内存引用的局部性更好
  • 购买具有较大缓存的硬件
  • (可能)重新设计您的算法以使用GPU或其他策略来减少内存流量
在C或C++中记录你的存在可以提高性能,但是同样的内存位置问题也会影响到你。


我不知道有什么工具可以用来测量Java应用程序中的缓存性能。

定义“非常慢”。我不认为java访问数组是件很慢的事情。?你的ram怎么样?也许你的ram中有所有的内存,操作系统交换了很多,所以它会转到磁盘来获取你的数组位置。用几个字符试试,看看性能如何,而不使用太多的ram。@Andreas我用8324701在一个字符数组上搜索了4000种不同的模式然后我运行了相同的测试,但我更改了
transFunc[preCompRow[q]+T[I]
for
transFunc[T[I]]
只花了9秒。@leoxs我在两个测试的执行过程中没有看到任何交换活动。我正在使用2 GB的heapI。你真的需要性能,你可以用C编写代码,并将其作为java项目中的一个模块使用。如果可以并行运行,可以考虑使用线程,或者更好,在GPU上这样做。我还认为bottleneck在+,但我测试了几个案例
transFunc[T[I]]
transFunc[1+T[I]]
transFunc[T[I]]
,所有这些都有合理的性能,但每次我在索引中添加预编译行[q]时,整个事情都会出错。当我将
q
修正到某个值时,事情会非常快,例如
transFunc>[preCompRow[1]+T[I]]
。我的结论是问题在于
q
的值,在循环的每一次过程中,它可以取模式的1到#个字符之间的值。我认为您的思路是正确的。因为
T
值是
char
,它们可能被限制为ASCII,即在32到126的数字范围内。
transFunc[T[i]]
将只访问
transFunc
的索引,整个范围(总共760字节)将很快在一级缓存中。--对于
transFunc[preCompRow[q]+T[i]]
,我们不知道
preCompRow
值的范围,即
transFunc
的大小,但如果该值很大,则将其加载到一级缓存需要更长的时间,甚至可能超过
L1
缓存的大小,从而大大增加缓存未命中率,即使对于相同的索引值也是如此。是的,我认为问题与缓存有关。
preComRow
只是一个模式大小的int数组。行是预计算的,因为我使用2D数组作为转换函数,但表示为1D数组(我认为我在JAVA 2D数组模拟方面有问题),然后形式为arr[I][j]的数组表示为arr[(I*步数)+j],我对此进行了预计算,以避免搜索循环中的计算。问题是我知道
preCompRow
的范围。我忘了提到,我正在搜索的模式非常短,只有50个字符长。如果您为您的问题创建MCVE,以便我们可以观察并诊断“缓慢访问”,这将对我们有所帮助如果没有一个适当的MCVE,我认为除了猜测之外,不可能做任何事情。