《嵌入式 - 嵌入式大杂烩》CoreMark性能测试

news2024/11/28 10:34:52

1 CoreMark简介

CoreMark是由EEMBC(Embedded Microprocessor Benchmark Consortium)的Shay Gla-On于2009年提出的一项基准测试程序,CoreMark的主要目标是简化操作,并提供一套测试单核处理器核心的方法。测试标准是在配置参数的组合下单位时间内运行的CoreMark程序次数(单位:CoreMark/MHz),该数字值越大则说明测试的性能越好。

目前在嵌入式CPU行业中普遍公认的性能测试指标的标准主要使用以下三种,MIPS、Dhrystone、Coremark,而CoreMark与Dhrystone一样,拥有体积小、方便移植、易于理解、免费并且显示单个数字基准分数。与Dhrystone不同的是,Dhrystone的主要部分实际上暴露了编译器优化工作负载的能力,而不是实际MCU或CPU的能力,的性能,而CoreMark具有特定的运行和报告规则,从而可以避免由于所使用的编译库不同而导致的测试结果难以比较。

官网地址

2 CoreMark移植

笔者这里使用STM32来演示。

2.1 CoreMark源码下载

首先去CoreMark 官网下载CoreMark源码。

CoreMark 移植所需的如下:

 core_list_join.c
 core_main.c
 core_matrix.c
 core_state.c
 core_util.c
 coremark.h
 simple/core_portme.c
 simple/core_portme.h

2.2 移植CoreMark

1)拷贝CoreMark文件到工程
准备一个STM32工程,将CoreMark所需的文件添加放到工程目录中。

在这里插入图片描述

2)添加文件到工程
接下来要做的就是添加 CoreMark 代码。因为 core_main.c 文件里已经包含了一个 main 函数,所以需要在工程中将默认创建的 main.c 文件删除。

完成后的工程文件结构如下:

在这里插入图片描述

2.3 配置 Coremark 文件

我们需要在 core_portme.c 中添加初始化的代码,并根据不同的计时方法修改 core_portme.c 中计时相关函数和代码。

2.3.1 添加初始化代码

core_portme.c 中的 portable_init 函数在 core_main.c 的 main 函数中首先被调用, 平台的初始化的函数(时钟,GPIO,串口,缓存) 可以放在这里。

修改前:

void portable_init(core_portable *p, int *argc, char *argv[])
{

    (void)argc; // prevent unused warning
    (void)argv; // prevent unused warning

    if (sizeof(ee_ptr_int) != sizeof(ee_u8 *))
    {
        ee_printf(
            "ERROR! Please define ee_ptr_int to a type that holds a "
            "pointer!\n");
    }
    if (sizeof(ee_u32) != 4)
    {
        ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n");
    }
    p->portable_id = 1;
}

修改后:

void portable_init(core_portable *p, int *argc, char *argv[])
{
    ST_BSP_USART_Dev BSP_USART_Dev0 = USART_DEV0_CONFIG;

    /* Configure the NVIC Preemption Priority Bits */  
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    /* USART1 配置模式为 115200 8-N-1,中断接收 */
    BSP_USART_Init(&BSP_USART_Dev0, 115200, 0, 1);

    printf("The CoreMark is runing,Please Wait...\r\n");
    if (sizeof(ee_ptr_int) != sizeof(ee_u8 *)) {
        ee_printf("ERROR! Please define ee_ptr_int to a type that holds a pointer!\n");
    }
    if (sizeof(ee_u32) != 4) {
        ee_printf("ERROR! Please define ee_u32 to a 32b unsigned type!\n");
    }
    p->portable_id=1;
}

2.3.2 修改计时相关代码

start_time/ stop_time/ get_time 这几个函数是 coremark 程序运行时计算程序运行时间所用。 这里使用 system tick 进行计时, system tick 配置为 1ms 的中断间隔。 system tick 中断函数中更新 Tick 的值,每进一次中断加 1。所以还需要修改system tick 的中断处理函数。

1)在 core_portme.c 中按下表找到需要修改的地方。

修改前:

void start_time(void)
{
    GETMYTIME(&start_time_val);
}

void stop_time(void)
{
    GETMYTIME(&stop_time_val);
}

CORE_TICKS get_time(void)
{
    CORE_TICKS elapsed
        = (CORE_TICKS)(MYTIMEDIFF(stop_time_val, start_time_val));
    return elapsed;
}


#define NSECS_PER_SEC CLOCKS_PER_SEC
#define CORETIMETYPE clock_t
#define GETMYTIME(_t) (*_t=clock())
#define MYTIMEDIFF(fin,ini) ((fin)-(ini))
#define TIMER_RES_DIVIDER 1
#define SAMPLE_TIME_IMPLEMENTATION 1
……
static CORETIMETYPE start_time_val,
stop_time_val;	

修改后:

void start_time(void) 
{ 
	Tick = 0;
	SysTick_Config(SystemCoreClock/1000);
}

void stop_time(void)
{
    SysTick->CTRL &=SysTick_Counter_Disable;
    /* Clear the SysTick Counter */
    SysTick->VAL = SysTick_Counter_Clear;
}

CORE_TICKS get_time(void)
{
    CORE_TICKS elapsed =(CORE_TICKS)Tick;
    return elapsed;
}

//#define NSECS_PER_SEC CLOCKS_PER_SEC
//#define CORETIMETYPE clock_t
//#define GETMYTIME(_t) (*_t=clock())
//#define MYTIMEDIFF(fin,ini) ((fin)-(ini))
//#define TIMER_RES_DIVIDER 1
//#define SAMPLE_TIME_IMPLEMENTATION 1
……
//static CORETIMETYPE start_time_val,stop_time_val;
#define EE_TICKS_PER_SEC (NSECS_PER_SEC TIMER_RES_DIVIDER)	#define EE_TICKS_PER_SEC 1000

2) 在 core_portme.c 文件中添加新定义的变量和函数

#define SysTick_Counter_Disable ((uint32_t)0xFFFFFFFE)
#define SysTick_Counter_Enable ((uint32_t)0x00000001)
#define SysTick_Counter_Clear ((uint32_t)0x00000000)
__IO uint32_t Tick;

system tick 的中断处理函数在 stm32f10x_it.c 中。stm32f10x_it.c 文件包含所有中断处理入口函数。根据不同的平台, 这个文件的名字稍有不同。找到 SysTick_Handler 函数进行修改。

修改前:

/**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
void SysTick_Handler(void)
{

}

修改后:

/**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
void SysTick_Handler(void)
{
    extern __IO uint32_t Tick;
    Tick++;
}

2.3.3 CoreMark 运行配置

1)设置迭代次数
CoreMark 要求程序运行的最短时间至少是 10s, 根据使用的系统时钟等情况,可以在 core_portme.h 中修改迭代次数。

#define ITERATIONS 12000

2)设置打印信息

根据具体所用的编译器版本,优化配置进行修改。

修改前:

#ifndef COMPILER_FLAGS
#define COMPILER_FLAGS FLAGS_STR /*
"Please put compiler flags here (e.g. -o3)"
*/
#endif

修改后

#ifndef COMPILER_FLAGS
#define COMPILER_FLAGS "-Ohs -
no_size_constraints"
#endif

3) 修改优化等级。

Options->C/C++ ->Optimization, 选择O3以达到最优的运行速度。

在这里插入图片描述

3 运行结果

接上串口,复位打印信息如下:

STM32F103

在这里插入图片描述

STM32F429

在这里插入图片描述

GD32F2

在这里插入图片描述

从结果可以看出STM32F429的性能最佳,而且差距还很大。



欢迎访问我的网站

BruceOu的哔哩哔哩
BruceOu的主页
BruceOu的博客
BruceOu的CSDN博客
BruceOu的简书
BruceOu的知乎

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

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

相关文章

【树莓派不吃灰系列】快速导航

目录1. 通用篇2. Python篇3. 编程IO篇❤️ 博客主页 单片机菜鸟哥,一个野生非专业硬件IOT爱好者 ❤️❤️ 本篇创建记录 2022-11-06 ❤️❤️ 本篇更新记录 2022-11-06 ❤️🎉 欢迎关注 🔎点赞 👍收藏 ⭐️留言 📝&…

Slave_IO_Running: No 的解决

原因: 两台主从数据库的uuid相同了(没猜错的话,各位的第二台虚拟机都是克隆了第一台,然后就改了个ip对吧)。 解决办法: 必须跟着步骤来,一步也不能多,更不能少,请仔细…

arcgis 生成切片并发布服务

需要准备: 1、需要进行切割的tif文件; 2、切片方案文件 需要确认: 1、tif文件的数据源坐标系; 2、现有切片方案能否满足需求; 3、部署的地图引擎是经纬度投影还是墨卡托投影; 具体操作流程: 1…

TCP/IP协议数据链路层

目录 一、数据链路层和网络层的关系 二、以太网 1、以太网格式 2、认识MTU 三、ARP协议 1、ARP协议的作用 2、ARP协议的工作流程 3、ARP数据报的格式 4、思考:浏览器中输入url后, 发生的事情(经典面试题) 一、数据链路层和网络层的…

通信行业的必备网站

今天突然看到一首诗感触满满: 官策作者陈京 生如蝼蚁,当有鸿鹄之志! 命如纸薄,应有不屈之心! 大丈夫生于天地间,岂能郁郁久居人下。 当以梦为马,不负韶华。 乾坤未定,你我皆是黑马&…

西安交大讲座-实际场景(3个)出发,用户检测方式,数据驱动的网络用户行为分析建模与异常检测

讲座搬运,侵删! 目录 研究背景 研究问题 问题与挑战 网络舆情分析 政策法规知识图谱 构建利益方群体识别模型 系统 ​编辑 第二个工作-异常群体映射与定位 多源社交网络用户身份管理 不用场景的用户身份映射 多个平台关联 黑产检测 基于图模型…

基于FreeCAD的dxf转机械手代码的一种实现方法

dxf文件在2D图形中使用广泛,将图形文件自动转换为机械手可识别的轨迹代码是机械手全自动化中一个软件衔接节点。理想的轨迹自动化转换程序可以在电脑里面直接虚拟仿真生成机械手轨迹,简化现场人员机械手示教流程,在效率和远程支持上有着实际的…

2021 神经网络压缩 (李宏毅

首先,为什么需要对神经网络模型进行压缩呢?我们在之前的课程中介绍过很多大型的深度学习模型,但当我们想要将这些大模型放在算力比较小的边缘设备或者其他IoT设备里面,就需要对大模型进行压缩。 Lower latency:低时延 …

刷题笔记之八(字符串通配符+参数解析+计算日期到天数)

目录 1. dateadd(datepart,number,date)函数是在日期中添加或减去指定的时间间隔 2. DML数据库操作语言负责数据的增删查改 3. 修改表结构的关键字都是alter table 表名,再加修改的语句 4. between and条件查询范围前闭后闭 5. 使用索引…

目标检测(1)—— 基础知识和常用数据集

一、什么是目标检测 一张图片,经过网络后得到输出,检测出感兴趣目标的一个位置,比如下图的车在什么地方,狗在什么地方;还要输出相应位置的目标是什么类别的。 目标检测:位置+类别 矩形框&…

vue 的 render 函数的用法:new Vue({ render: h => h(App), }).$mount(‘#app‘)

render函数的作用 render函数是vue通过js渲染dom结构的函数createElement,约定可以简写为h 官方文档中是这样的,createElement 是 Vue.js 里面的 函数, 这个函数的作用就是生成一个 VNode节点, render 函数得到这个 VNode 节点之后…

记一次内网靶机实战

文章目录0x00 边界服务器0x01 一层网络0x01-01 fscan内网扫描0x01-02 配置frp设置socks5代理0x01-03 访问内网的(10.10.135.66)0x01-04 访问内网的(10.10.135.35)0x01-05 访问内网的(10.10.135.190)0x02二层…

稀疏数组

章节目录:一、稀疏数组1.1 需求引出1.2 基本介绍1.3 应用实例二、结束语一、稀疏数组 1.1 需求引出 假设我们有个五子棋程序,使用1来表示黑子,2表示蓝子,0表示没有棋盘落子,并且需要对棋盘数据进行存储。 前端棋盘示意…

546、Zookeeper详细入门教程系列 -【Zookeeper内部原理】 2022.11.06

目录一、Zookeeper内部原理1.1 节点类型(Znode)1.2 Stat结构体1.3 监听器原理1.4 选举机制1.5 写数据流程二、最后三、参考链接一、Zookeeper内部原理 1.1 节点类型(Znode) 持久:客户端和服务器断开后,创…

汇编语言程序设计 --- 一元二次方程ax2+bx+c=0求解(含注释详细源代码 + 实验报告)

目录一、实验内容二、实验说明三、实验报告要求四、实验目的五、 程序流程图六、内存变化情况七、实验报告 源程序代码 (详细注释)一、实验内容 一元二次方程ax2bxc0求解。 二、实验说明 1、要求在数据段中定义a、b、c、x,a、b、c初值不限…

【晶振专题】案例:为什么对着STM32低速32.768K晶振哈口气就不起振了?

本案例发现在一个工装产品上,首批一共做了10几台样机。发现有的样机在开机的时候读取不到RTC,有的样机却可以。读不到RTC是概率性出现的,发生在第一次上电的情况。开始他怀疑是环境问题,会不会和温度有关,于是同事在家做了大量的实验,发现对晶振吹口气就能让晶振不起振,…

01-nacos在Windows系统单机,集群的安装

一 ,什么是Nacos?官网 Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service的首字母简称,一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。Nacos 提供了一组简单易用的特性集,能够快速实现动态服务发现、服务…

Flutter教程之在 Flutter 中显示 TextField 上的日期选择器(教程含源码)

首先我们必须知道它是什么 Flutter 中的日期选择器——Flutter 日期范围选择器是一个轻量级的小部件,它允许用户轻松选择单个日期、多个日期或一个日期范围。日期选择器提供月、年、十年和世纪视图选项,以快速导航到所需的日期。 让我们实现它… 日期选择器—— 我们将在 …

机场调度管理系统(客户端+服务器端+Java+MySQL)

目 录 1 绪论 1 1.1 项目背景 1 1.2 项目目的 1 1.3 项目可行性分析 2 2 技术介绍 3 2.1 Java技术 3 2.1.1 Java技术简介 3 2.1.2 Java面向对象的特征 3 2.2Javascript和jQuery技术 4 2.1.1 Javascript 简介 4 2.2.2 jQuery-easyui简介 4 2.3Jsp技术 5 2.4 Mysql 5 3 需求分析…

python基础05——字典:dict及集合:set,看这篇文章就够了

目录1字典: dict 无序可变序列1.1 创建1.1.1 用{ }创建字典1.1.2 用dict创建字典1.1.3 用zip创建字典1.1.4 用fromkeys创建字典1.2 查询1.2.1 通过键访问字典的值1.2.1.1 直接取键 dict[ ]1.2.1.2 get()1.2.2 查看字典的键和值1.2.2.1 返回所有的键 dict.keys()1.2.2.2 返回所有…