IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 如何测试一次内存访问的耗时? -> 正文阅读

[嵌入式]如何测试一次内存访问的耗时?

程序在运行的过程访问主存每次是按cpu cache line 64B访问的(主流cpu cache line一般都是64B),如果命中L1 cache耗时约1ns,如果命中L2 cache耗时约3ns,如果命中L3 cache耗时约12ns,如果访问内存约50-100ns,上面这些数据都是从些网上的文章资料得知的。
如何写段代码测试下内存的访问时间,结果应该接近50-100ns ,本文介绍下测试方法:
1. 申请几段连续的虚拟内存,总大小4GB;
2. 给申请的4GB内存按页的大小4KB间隔,每页第1个字节写入值,目的是访问内存,让系统真正的分配物理内存;
3. 按照步长64B 128B … 4096B分别测试下按顺序访问已申请的4GB内存;
注:测试机器要尽量干净,未运行服务程序,以免测试过程中产生cpu切出运行其它服务程序,影响计时;


#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>

long long ustime(void) 
{
    struct timeval tv;
    long long ust;

    gettimeofday(&tv, NULL);
    ust = ((long)tv.tv_sec)*1000000;
    ust += tv.tv_usec;
    return ust;
}

#define LOOPLEN  4*1024
#define STEPLEN  64

#define LOOPLENREFRSH 512

typedef struct bigData{
    char buf[1024*1024]; /* 1MB buffer */
} bigData;

struct bigData * apstData[LOOPLEN];
struct bigData * apstDataTmp[LOOPLENREFRSH];

void test()
{
    long long t1;
    long long t2;
    long long diff;
    int i,j;
    int count = 0;
	struct bigData * tmpData;
	char *pcTmp;
	int iN = 0;
    printf("------------------------\n");

    /* 记录开始时间,测试内存的写时间 */
    t1 = ustime();
	
	for (i = 0; i < LOOPLEN; i++)
	{
        tmpData = apstData[i];
		/* 每次访问64B,目前主流CPU都是按cache-line 64B进行一次内存的访问 */
		for (j = 0; j < sizeof(struct bigData); j += STEPLEN)
		{
			/* write */
			*((int *)((char *)tmpData + j)) = 1;
			count ++;
		}
    }
	/* 记录结束时间 */
    t2 = ustime();
    diff = t2-t1;
    printf("diff time:%lld000ns, count:%d, memory write time: %lldns\n",diff, count, diff*1000/count);


    count = 0;
	/* 记录开始时间,测试内存的读取时间 */
    t1 = ustime();
	
	for (i = 0; i < LOOPLEN; i++)
	{
        tmpData = apstData[i];
		/* 每次访问64B,目前主流CPU都是按cache-line 64B进行一次内存的访问 */
		for (j = 0; j < sizeof(struct bigData); j += STEPLEN)
		{
			iN += *((int *)((char *)tmpData + j));
			count ++;
		}
    }
	
	/* 记录结束时间 */
    t2 = ustime();
    diff = t2-t1;
    printf("diff time:%lld000ns, count:%d, memory read  time: %lldns, result:%d\n",diff, count, diff*1000/count, iN);
    return; 
}

void refreshCache()
{
    int i,j;
	struct bigData * tmpData;
	int iN = 0;

	for (i = 0; i < LOOPLENREFRSH; i++)
	{
        tmpData = apstDataTmp[i];
		/* 每次访问64B,目前主流CPU都是按cache-line 64B进行一次内存的访问 */
		for (j = 0; j < sizeof(struct bigData); j += 64)
		{
			/* write */
			*((int *)((char *)tmpData + j)) = 1;
		}
    }

    return; 
}


void alloc(struct bigData ** apstDataParam, int iLoop)
{
	int i,j;
	struct bigData * tmpData;
	char *pcTmp;
	/* 申请4*1024个1024*1024B的虚拟内存 */
	printf("start alloc virtual memory set value\n");
	for (i = 0; i < iLoop; i++)
	{
        apstDataParam[i] = malloc(sizeof(struct bigData));
    }
	
	/* 每页的内存访问一次,产生缺页中断,分配物理内存 */
	printf("start physical memory set value\n");
	for (i = 0; i < iLoop; i++)
	{
        tmpData = apstDataParam[i];
		/* 每页长 4KB 访问一次,以便OS分配物理内存 */
		for (j = 0; j < sizeof(struct bigData); j += 4096)
		{
			pcTmp = (char *)tmpData + j;
			*pcTmp = '1';
		}
    }
	
}

void main()
{
	alloc(apstData, LOOPLEN);
	
	/* 多访问未参与测试计时的内存,刷cache,降低cache命中率 */
	alloc(apstDataTmp, LOOPLENREFRSH);
	refreshCache();
	
	/* 多次测试 */
	test();
	refreshCache();  /* 刷cache */
	test();
	refreshCache();  /* 刷cache */
	test();
	refreshCache();  /* 刷cache */
	test();

    return; 
}

ARM 测试:
1.STEPLEN 设置成 64,树莓派4B,arm 64,600元一台整机还是8G内存,测试结如下: 写约64ns,读15ns,感觉读的时间不准

在这里插入图片描述

2.STEPLEN 设置成 4096,树莓派4B,arm 64,测试结如下:写约42ns,读40ns,稍理想点

在这里插入图片描述

Intel测试:
1.STEPLEN 设置成 64,腾讯云虚机,测试结如下: 写7ns,读6ns估计存在大量cache命中
在这里插入图片描述

2.STEPLEN 设置成 4096,腾讯云虚机,测试结如下:写45ns,读20ns
在这里插入图片描述


综合结论:
arm64 写耗时:约65ns 读耗时:约40ns
x86_64 写耗时:约45ns 读耗时:约20ns
这个结果还不算特别离谱
不同体系统架构L1 L2 cache的机制不一样,所以要把访问步长STEPLEN多设置些64的倍数,分别测试下,以降低cache命中,提升测试结果准确性。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-07-31 17:13:27  更:2021-07-31 17:13:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/2 22:55:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码