这代码居然有差别?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虚拟机》
目录
相关文章
|
Java Linux
linux中找到最耗CPU的那段Java代码
linux中找到最耗CPU的那段Java代码
|
2月前
|
调度
CPU调度器实现提示:针对特定体系结构代码【ChatGPT】
CPU调度器实现提示:针对特定体系结构代码【ChatGPT】
|
4月前
|
机器学习/深度学习 TensorFlow API
Keras是一个高层神经网络API,由Python编写,并能够在TensorFlow、Theano或CNTK之上运行。Keras的设计初衷是支持快速实验,能够用最少的代码实现想法,并且能够方便地在CPU和GPU上运行。
Keras是一个高层神经网络API,由Python编写,并能够在TensorFlow、Theano或CNTK之上运行。Keras的设计初衷是支持快速实验,能够用最少的代码实现想法,并且能够方便地在CPU和GPU上运行。
|
5月前
|
并行计算 异构计算 Python
python代码torch.device("cuda:0" if torch.cuda.is_available() else "cpu")是什么意思?
【6月更文挑战第3天】python代码torch.device("cuda:0" if torch.cuda.is_available() else "cpu")是什么意思?
491 4
|
6月前
|
Java Linux
Linux下如何定位最耗CPU的JAVA代码
Linux下如何定位最耗CPU的JAVA代码
78 0
|
11月前
|
监控 数据可视化 Java
双CPU监控的目的以及主流编程语言实现代码示例
监控CPU使用率可以帮助检测系统瓶颈和性能问题,有助于及时识别并解决故障。
484 2
|
监控 调度 Python
电脑监控软件所含的CPU资源监控的代码(使用psutil库)
本文使用psutil库来获取CPU使用率、运行的进程、CPU温度、风扇速度和CPU核心的工作情况。这些信息可用于自定义电脑监控软件的CPU资源监控功能
557 1
|
1天前
|
弹性计算 Kubernetes Perl
k8s 设置pod 的cpu 和内存
在 Kubernetes (k8s) 中,设置 Pod 的 CPU 和内存资源限制和请求是非常重要的,因为这有助于确保集群资源的合理分配和有效利用。你可以通过定义 Pod 的 `resources` 字段来设置这些限制。 以下是一个示例 YAML 文件,展示了如何为一个 Pod 设置 CPU 和内存资源请求(requests)和限制(limits): ```yaml apiVersion: v1 kind: Pod metadata: name: example-pod spec: containers: - name: example-container image:
|
10天前
|
存储 关系型数据库 MySQL
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
179 1
|
2月前
|
存储 关系型数据库 MySQL
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
111 5
下一篇
无影云桌面