这代码居然有差别?CPU友好的代码该这样写(4)

简介: 这代码居然有差别?CPU友好的代码该这样写

三、总结


再来回顾一下我们之前的问题。

image.png

C代码块 是横向优先的访问方式。

A代码块 里面对 arrays_A 的方式是横向顺序访问的,但是在处理 arrays_B 的时候就是纵向遍历的。

B代码块 所有的访问都是纵向的(不友好的遍历方式)。因为发挥不出CPU缓存的效果,所以性能最差。

Java的二维数组在内存里面是行连续的,但是行与行之间不一定连续。CPU在缓存大小有限的情况下,不可能把所有的数据都缓存下来。再加上每一层级访问速度的硬件限制,就导致了上面的性能结果。

相信大家也和我一样,知道原理之后,也不是那么迷惑了。

在实际的业务环境中,我们不一定能遇到这种纯计算的场景。但是我们还是应该尽量顺序访问数据,不管是什么样的数据。投其所好,方能够优化代码性能。

其次,我们在访问数据的时候,还是需要了解各种语言背后实际的存储结构和CPU的缓存原理,本次是讲述的是Java,但是这个思想其他语言其实也是受用的。


四、附件

4.1 运行的环境

系统参数:

JMH version: 1.36

VM version: JDK 11.0.13, Java HotSpot(TM) 64-Bit Server VM, 11.0.13+10-LTS-370

JMH version: 1.36
VM version: JDK 11.0.13,Java HotSpot(TM) 64-Bit Server VM,11.0.13+10-
型号名称:MacBook Pro
型号标识符:MacBookPro15,2
处理器名称:四核Intel Core i5
处理器速度: 2.4 GHz
处理器数目: 1
核总数: 4
L2缓存 (每个核) : 256 KB
L3缓存:6 MB
超线程技术:已启用
内存:16 GB
系统固件版本: 1715.60.5.0.0 (iBridge: 19.16.10647.0.0,0)


4.2 整个benchmark的java代码

ArrayTestBenchmark

import org.openjdk.jmh.annotations.*;
/**
*矩阵C=AB 的计算
*
* @author wzj*
* @date 2023/02/09
*/
@BenchmarkMode(Mode.AverageTime)
@State(value = Scope.Benchmark)
// 预热3次
@Warmup(iterations = 3, time = 1)
// 循环 10 次
@Measurement(iterations = 10, time = 1)
public class ArrayTestBenchmark {
private final int N = 1000;
private final int[][] arrays_A = new int[N][N];
private final int[][] arrays B = new int[N][N];
@Setup
public void setUp() {
for (int i=; i< N; i++) {
for (int j =0; j< N; j++) {
arrays_A[i][j] = i + j;
arrays B[i][jl = i + j;
}
}
}
@Benchmark
public void ijk() {
final int[][] arrays_C = new int[N] [N];
for (int i=0; i<N; i++) {
for (int j=0; j < N; j++) {
int sum = 0;
for (int k=0; k < N; k++){
sum += arrays A[i][k] * arrays B[k][j];
}
arrays_C[i][j] += sum;
}
}
assert arrays_C.length > 0;
}
@Benchmark
public void jik(){
final int[][] arrays_C = new int[N][N];
for (int j =@; j< N; j++) {
for (int i=@; i< N; i++) {
int sum = 0;
for (int k =; k< N; k++) {
sum += arrays A[i][k] * arrays B[k][j];
}
arrays_C[i][j] += sum;
}
}
assert arrays_C.length > 0;
}
@Benchmark
public void jki() {
final int[][] arrays_C = new int[N][N];
for (int j =; j < N; j++){
for (int k =0; k< N; k++) {
int r_B = arrays_B[k][j];
for (int i=@; i< N; i++) {
arrays_C[i][j] += arrays_A[i][k] * r_B;
}
}
}
assert arrays_C.length > 0;
}
@Benchmark
public void kji() {
final int[][] arrays_C = new int[N] [N];
for (int k =o; k < N; k++) {
for (int j =@; j < N; j++) {
int r_B = arrays_B[k][j];
for (int i=0; i< N; i++) {
arrays_C[i][j] += arrays A[i][k] * r_B;
}
}
}
assert arrays C.length > 0;
}
@Benchmark
public void kij() {
final int[][] arrays C = new int[N][N];
for (int k =; k < N; k++) {
for (int i=0; i < N; i++) {
int r A = arrays A[k][i];
for (int j=0; j <N; j++) {
arrays_C[i][j] += r_A * arrays_B[k][j];
}
}
}
assert arrays C.length > 0;
}
@Benchmark
public void ikj() {
final int[][] arrays_C = new int[N][N];
for (int i=0; i< N; i++) {
for (int k =o; k < N; k++) {
int r_A = arrays A[k][i];
for (int j =@; j < N; j++) {
arrays_C[i][j] += r_A *arrays_B[k][j];
}
}
}
assert arrays_C.length > 0;
}
}


4.3 多次运行benchmark的结果

image.png

引用:

  1. 《深入理解计算机操作系统》
  2. 《深入理解Java虚拟机》
目录
相关文章
|
7月前
|
Java Linux
linux中找到最耗CPU的那段Java代码
linux中找到最耗CPU的那段Java代码
|
1月前
|
Java Linux
Linux下如何定位最耗CPU的JAVA代码
Linux下如何定位最耗CPU的JAVA代码
38 0
|
6月前
|
监控 数据可视化 Java
双CPU监控的目的以及主流编程语言实现代码示例
监控CPU使用率可以帮助检测系统瓶颈和性能问题,有助于及时识别并解决故障。
434 2
|
7月前
|
监控 调度 Python
电脑监控软件所含的CPU资源监控的代码(使用psutil库)
本文使用psutil库来获取CPU使用率、运行的进程、CPU温度、风扇速度和CPU核心的工作情况。这些信息可用于自定义电脑监控软件的CPU资源监控功能
500 1
|
7月前
|
存储 缓存 Java
这代码居然有差别?CPU友好的代码该这样写(3)
这代码居然有差别?CPU友好的代码该这样写
33 0
这代码居然有差别?CPU友好的代码该这样写(3)
|
7月前
|
缓存
这代码居然有差别?CPU友好的代码该这样写(2)
这代码居然有差别?CPU友好的代码该这样写
34 0
这代码居然有差别?CPU友好的代码该这样写(2)
|
7月前
|
存储 缓存 Java
这代码居然有差别?CPU友好的代码该这样写(1)
这代码居然有差别?CPU友好的代码该这样写
58 0
这代码居然有差别?CPU友好的代码该这样写(1)
|
7月前
|
缓存 安全 Java
从CPU的视角看 多线程代码为什么那么难写!
当我们提到多线程、并发的时候,我们就会回想起各种诡异的bug,比如各种线程安全问题甚至是应用崩溃,而且这些诡异的bug还很难复现。我们不禁发出了灵魂拷问 “为什么代码测试环境运行好好的,一上线就不行了?”。 为了解决线程安全的问题,我们的先辈们在编程语言中引入了各种各样新名词,就拿我们熟悉的Java为例,不仅java语言自带了synchronized、volatile、wait、notify… ,jdk中各种工具包也是层出不穷,就比如单一个Lock,就可以有很多种实现,甚至很多人都谈锁色变。
60 0
|
9月前
|
机器学习/深度学习 缓存 Linux
很底层的性能优化:让CPU更快地执行你的代码
很底层的性能优化:让CPU更快地执行你的代码
|
1月前
|
Linux
Linux rsyslog占用内存CPU过高解决办法
该文档描述了`rsyslog`占用内存过高的问题及其解决方案。
95 4