《嵌入式 - 嵌入式大杂烩》CoreMark性能测试
创始人
2024-01-20 05:39:30

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 warningif (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的知乎

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
苁蓉的食用方法 鲜苁蓉的吃法有... 肉苁蓉号称“温而不热,补而不峻,暖而不燥,滑而不泄,故有从容之名。”历来也是传统药食同源的滋补佳品。...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
阳澄湖在哪里哪个省的 阳澄湖是... 点击题目下方苏州生活指南有用 有趣 有态度近期的阳澄湖度很高,3月24日,央视二套《第一时间》直播连...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...