动手测试:CPU的L1~L3级缓存和内存的读取速度测试

news2024/11/27 13:01:39

引言

在许多文章中指出了这些缓存的架构,速度差异等。纸上得来终觉浅,今天想实际写代码简单测试一下。

背景

现代计算机系统中,CPU缓存(L1、L2、L3)和主内存(RAM)之间的读取速度有着显著的差异。缓存的主要目的是提高数据访问的速度,从而提升整体的系统性能。本篇文章将通过一系列的测试来探索不同大小内存块的读写性能,从而揭示缓存和内存之间读取速度的变化规律。

在这里插入图片描述

测试思路

我们通过改变内存块的大小来观察缓存命中和未命中的情况。具体而言,我们会从小块内存(128字节)开始测试,逐渐增加到较大的内存块(10GB),以此来观察性能曲线的变化。

测试代码

以下是用于测试的C++代码:

#include <iostream>
#include <vector>
#include <chrono>
#include <cstdlib>

// 记录读写操作的时间
void testMemoryAccessSpeed(size_t blockSize) {
	size_t totalBytes = 1024ull * 1024 * 1024 * 100; // 总共读写100GB的数据
	size_t iterations = totalBytes / blockSize;
	std::vector<size_t> buffer(blockSize / sizeof(size_t));
	// 初始化计时器
	auto start = std::chrono::high_resolution_clock::now();
	// 执行读写操作
	for (size_t i = 0; i < iterations; ++i) {
		memset(buffer.data(), 551546, buffer.size() * sizeof(size_t));
	}
	// 记录结束时间
	auto end = std::chrono::high_resolution_clock::now();
	auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

	// 输出结果
	if (blockSize > 1024 * 1024) {
		std::cout << "Block Size (MB): " << blockSize / 1024 / 1024 << ", Time (ms): " << duration.count() << " Loops:"<< iterations << std::endl;
	}
	else if (blockSize > 1024) {
		std::cout << "Block Size (KB): " << blockSize / 1024 << ", Time (ms): " << duration.count() << " Loops:" << iterations << std::endl;
	}
	else {
		std::cout << "Block Size ( B): " << blockSize << ", Time (ms): " << duration.count() << " Loops:" << iterations << std::endl;
	}
}

int main() {
	// 测试不同大小的内存块
	std::vector<size_t> blockSizeVec = {
		128, 512, 1024, 2 * 1024, //128B ~ 2KB
		4 * 1024, 64 * 1024, 512 * 1024, 4 * 1024 * 1024,  // 4KB ~ 4 MB
		16 * 1024 * 1024, 64 * 1024 * 1024, 256 * 1024 * 1024, 512 * 1024 * 1024,  // 16M ~ 512M
		1024 * 1024 * 1024, 2ull * 1024 * 1024 * 1024, 5ull * 1024 * 1024 * 1024, 10ull * 1024 * 1024 * 1024  // 1G ~ 10G
	};
	const size_t maxBlockSize = 128 * 1024 * 1024; // 最大到128MB

	for (auto it : blockSizeVec) {
		testMemoryAccessSpeed(it);
	}

	return 0;
}

测试的硬件平台为:

在这里插入图片描述
在这里插入图片描述

测试结果

以下是测试代码的输出:
在这里插入图片描述

结果粗略评估和解释

  1. 超小块内存(小于1KB)

    • 当内存块较小(如128字节)时,需要执行的循环次数成倍增加,整体的耗时更多在循环指令和函数调用(memset)上,而非数据读取。
    • 随着内存块大小的增加,循环次数减少,内存读写开始成为瓶颈,数据开始有意义。
  2. 小块内存(1KB至4KB)

    • 当内存块较小时,读写操作主要发生在L1缓存中,因此时间较长。
    • 随着内存块大小的增加,L1缓存的利用率下降,但L2缓存开始发挥作用,因此时间逐渐增加。
  3. 中等大小内存块(4KB至4MB)

    • 在这个范围内,L2缓存成为主要存储介质,性能较高。
    • 当内存块大小增加到一定程度,L2缓存开始饱和,性能下降。
  4. 大块内存(4MB至30MB)

    • L3缓存成为主要存储介质,性能再次提高。
    • 当内存块进一步增加到几十MB时,L3缓存也逐渐饱和,性能趋于稳定。
  5. 超大块内存(30MB及以上)

    • 超过L3缓存的容量后,性能受内存读取速度的限制,因此时间较为稳定。

excel 作图分析

在这里插入图片描述
在上图中,红色参考线是根据CPU-Z给出的单核心最大的L1~L3的缓存大小参考。注意,横坐标的BlockSize的增长不是线性增长的,但纵坐标轴Time是线性的。

从上图可以根据Time来粗略评估L1~L3再到内存的性能,我们选取了这几个样本点作为各个缓存性能的代表:
在这里插入图片描述

我的测试结论

根据选取的样本点,即可得出不同存储类型的性能参考:
在这里插入图片描述

上面的L1数据不是特别严谨,因为在块较小时,在循环和函数调用上会有额外的耗时,因此L1的性能应该比测试数据更高。具体高多少,可以根据前面的超小块内存测试结果进行评估。

网上其他相关测试的结论

在这里插入图片描述
在这里插入图片描述

总结

综合网上的资料和我的实践结论,基本可以得出如下概念:

  1. L1的速度是L2的2~5倍,我的测试结果是3.8倍
  2. L2的速度是L3的2~3倍,我的测试结果是1.8倍
  3. L3的速度是内存的3~7倍,我的测试结果是2.4倍(DDR5@4000M)。

这里的性能测试结果仅仅是上面的代码的运行耗时结果,不代表在大部分场景下L3的性能比内存高3~7倍。CPU访问内存需要经过复杂的内存控制器,主板的内存总线,再到内存控制器等复杂路径,每次读写也要操作一系列内存寄存器,从程序的角度来看,读写内存的延时要远远大于L3。从上图AIDA的测试结果中也能看出,内存的延时是L3的十倍。
对于实际程序运行的情况,内存延时带来的耗时增加是更严重的,这也是现代CPU把L3缓存做到30MB这么大的重要原因。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2180751.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构之链表(2),双向链表

目录 前言 一、链表的分类详细 二、双向链表 三、双向链表的实现 四、List.c文件的完整代码 五、使用演示 总结 前言 接着上一篇单链表来详细说说链表中什么是带头和不带头&#xff0c;“哨兵位”是什么&#xff0c;什么是单向什么是双向&#xff0c;什么是循环和不循环。然后实…

U盘恢复数据工具:让数据失而复得的魔法

优盘里数据丢失无疑会给我们的工作和生活带来诸多不便。幸运的是&#xff0c;优盘数据恢复软件应运而生&#xff0c;它们如同数据的守护者&#xff0c;为我们提供了找回丢失数据的希望。这次我们就一同来探讨u盘恢复数据有什么方法吧。 1.福昕恢复数据 链接直达&#xff1a;h…

AutoSar 通信服务架构,CAN通信诊断详解

文章目录 Com&#xff08;通信服务模块&#xff09;PDU的定义和结构PDU的分类IPDU Mux 模块PDU R 模块&#xff08;路由&#xff09;Bus TP 模块BUS InterfaceCanIf模块LinIf模块 发送数据示例&#xff08;CAN报文&#xff09;接收数据示例&#xff08;CAN报文&#xff09;通信…

监控告警功能详细介绍及操作演示:运维团队的智能保障

在当今这个信息化高速发展的时代&#xff0c;运维团队面临着前所未有的挑战。为了确保系统的稳定性和高效运维&#xff0c;监控告警功能成为了运维团队不可或缺的得力助手。本文将详细介绍我们的监控告警功能&#xff0c;并结合实际操作页面进行演示&#xff0c;帮助运维团队更…

Docker入门指南:快速学习Docker的基本操作

为什么需要Docker 有时我们在本地开发好程序并成功运行之后&#xff0c;却在服务器上运行不起来&#xff0c;通过观察日志通常会发现&#xff0c;哦原来是这个库没安装&#xff0c;于是我们就需要先安装需要用到的库&#xff0c;然后再启动服务你可能还会发现用到的数据库信息…

《Linux从小白到高手》理论篇(六):Linux软件安装一篇通

List item 本篇介绍Linux软件安装相关的操作命令&#xff0c;看完本文&#xff0c;有关Linux软件安装相关操作的常用命令你就掌握了99%了。 Linux软件安装 RPM RPM软件的安装、删除、更新只有root权限才能使用&#xff1b;查询功能任何用户都可以操作&#xff1b;如果普通用…

真正的Open AI ——LLaMA颠覆开源大模型

1. LLaMA 简介 LLaMA&#xff08;Large Language Model Meta AI&#xff09;是由Meta&#xff08;原Facebook&#xff09;推出的一个大型语言模型系列&#xff0c;旨在通过更小的模型规模和更少的计算资源&#xff0c;实现与其他主流语言模型&#xff08;如GPT&#xff09;相媲…

spring简短注入

新建bean 创建set方法 jpackage com.dependency.spring6.bean;import org.slf4j.Logger; import org.slf4j.LoggerFactory;public class User {private static final Logger LOGGER LoggerFactory.getLogger(User.class);private String username;private String password;pr…

RPA跨流程复用元素技巧|实在RPA研究

为什么要跨流程复用元素 在 RPA 操作中&#xff0c;元素至关重要&#xff0c;因为自动化的本质就是模拟人类对元素的操作。基本上&#xff0c;每个流程都会包含若干个元素。对于同时维护多个流程的用户而言&#xff0c;相似的流程包&#xff0c;甚至是同一个元素。例如电商用户…

Solidworks斜接法兰快速绘制钣金箱体

Solidworks斜接法兰快速绘制钣金箱体 Chapter1 Solidworks斜接法兰快速绘制钣金箱体 Chapter1 Solidworks斜接法兰快速绘制钣金箱体 0.5mm间距为钣金焊接的预留焊缝。

Linux云计算 |【第四阶段】RDBMS1-DAY6

主要内容&#xff1a; MySQL索引&#xff08;索引分类、创建索引&#xff09;、用户及授权&#xff08;创建用户并授权、查看授权、撤销授权、授权库mysql&#xff09;、root密码恢复、备份、使用mysqldump进行逻辑备份、Percona 一、MySQL索引 1、基本概念 MySQL 索引(Inde…

给虚拟机安装操作系统以及无密码SSH登录

安装完虚拟化软件VMware Workstation Pro 17之后&#xff0c;我们下载了Ubuntu光盘映像文件&#xff0c;上次说演示desktop版的安装&#xff0c;但是考虑到后面要部署数据库&#xff0c;所以为了方便起见还是下载sever服务器版。 文件还挺大&#xff0c;在等待下载完成这会我们…

基于SpringBoot的休闲娱乐代理售票系统设计与实现

1.1研究背景 21世纪&#xff0c;我国早在上世纪就已普及互联网信息&#xff0c;互联网对人们生活中带来了无限的便利。像大部分的企事业单位都有自己的系统&#xff0c;由从今传统的管理模式向互联网发展&#xff0c;如今开发自己的系统是理所当然的。那么开发休闲娱乐代理售票…

C++那些事之内存优化

C那些事之内存优化 通常程序运行时内存是一个比较大的问题&#xff0c;如何减少内存占用和提升访问速度是至关重要。为了解决这些问题&#xff0c;C20 引入了 no_unique_address 特性&#xff0c;并结合空基类优化&#xff08;EBO, Empty Base Optimization&#xff09;&#x…

33 指针与数组:数组名与指针的关系、使用指针遍历数组、数组指针、指针数组、字符指针

目录​​​​​​​ 1 数组名与指针的关系 1.1 数组名 1.2 对数组名取地址 1.3 数组名与指针的区别 1.3.1 类型不同 1.3.2 sizeof 操作符的行为不同 1.3.3 & 操作符的行为不同 1.3.4 自增自减运算的行为不同 1.3.5 可变性不同 2 使用指针遍历数组 2.1 使用 *(nu…

智能网联汽车飞速发展,安全危机竟如影随形,如何破局?

随着人工智能、5G通信、大数据等技术的飞速发展&#xff0c;智能网联汽车正在成为全球汽车行业的焦点。特别是我国智能网联汽车市场规模近年来呈现快速增长态势&#xff0c;彰显了行业蓬勃发展的活力与潜力。然而&#xff0c;车联网技术的广泛应用也带来了一系列网络安全问题&a…

Mybatis知识

1. 基础知识 mybatis是基于java的持久层框架&#xff0c;它内部封装了jdbc&#xff0c;使开发者只需要关注sql语句本身&#xff0c;而不需要花费精力去处理加载驱动&#xff0c;创建连接&#xff0c;创建statement等繁杂的过程。 通过xml或者注解的方式将要执行的各种sta…

序列化方式五——ProtoStuff

介绍 Protostuff是一个基于Java的高效序列化库&#xff0c;它使用Protocol Buffers&#xff08;简称protobuf&#xff09;协议&#xff0c;为Java对象提供高效、灵活且易用的序列化和反序列化方法。Protostuff的主要优势在于其高性能和简单的使用方式&#xff0c;相对于其他序…

C#多线程数据同步的几种方式(不同的锁)

无锁 多个关联数据无法完整获取修改 internal class Program{static void Main(string[] args){Console.WriteLine("Hello, World!");ThreadPool.QueueUserWorkItem(Thread1);ThreadPool.QueueUserWorkItem(Thread2);ThreadPool.QueueUserWorkItem(Thread3);Console…

SpringBoot框架在墙绘产品展示中的运用

4 系统设计 墙绘产品展示交易平台的设计方案比如功能框架的设计&#xff0c;比如数据库的设计的好坏也就决定了该系统在开发层面是否高效&#xff0c;以及在系统维护层面是否容易维护和升级&#xff0c;因为在系统实现阶段是需要考虑用户的所有需求&#xff0c;要是在设计阶段没…