coremark & dhrystone 移植要点
移植coremark & dhrystone要点
1. coremark
1.1 coremark 计算方法
计算的核心为下方的代码
start_time(); #if (MULTITHREAD > 1) /* 多线程的情况 */ #else /*单线程情况*/ iterate(&results[0]); #endif stop_time();
对于 iterate(&results[0]); 再追进去可以发现
void * iterate(void *pres) { ee_u32 i; ee_u16 crc; core_results *res = (core_results *)pres; ee_u32 iterations = res->iterations; res->crc = 0; res->crclist = 0; res->crcmatrix = 0; res->crcstate = 0; for (i = 0; i < iterations; i++) { crc = core_bench_list(res, 1); res->crc = crcu16(crc, res->crc); crc = core_bench_list(res, -1); res->crc = crcu16(crc, res->crc); if (i == 0) res->crclist = res->crc; } return NULL; }
而这里的iterations 会在results[0].iterations = get_seed_32(4);
函数中被赋值为ITERATIONS
,所以我们可以知道,其实coremark 就是获取了下面这些参数
- start_time();
- stop_time();
- iterations
然后通过下面的代码算出 循环次数÷时间
的结果,可以看下面的代码,用default_num_contexts * results[0].iterations / time_in_secs(total_time)
计算出了目标值。
但是实际我们看的分数是Iterations/Sec /MHZ
,即最后需要的结果是跑分/(你的时钟/1MHZ)
,例如我最后跑分是14,频率是5MHZ,那么我的实际结果是:14/(5/1) = 2.8 coremark/Mhz
/* and report results */ ee_printf("CoreMark Size : %lu\n", (long unsigned)results[0].size); ee_printf("Total ticks : %lu\n", (long unsigned)total_time); #if HAS_FLOAT /* 有浮点的情况 */ #else ee_printf("Total time (secs): %d\n", time_in_secs(total_time)); if (time_in_secs(total_time) > 0) ee_printf("Iterations/Sec : %d\n", default_num_contexts * results[0].iterations / time_in_secs(total_time)); #endif if (time_in_secs(total_time) < 10) { ee_printf( "ERROR! Must execute for at least 10 secs for a valid result!\n"); total_errors++; } ee_printf("Iterations : %lu\n", (long unsigned)default_num_contexts * results[0].iterations); ee_printf("Compiler version : %s\n", COMPILER_VERSION); ee_printf("Compiler flags : %s\n", COMPILER_FLAGS);
1.2 coremark 移植方法
由1.1 我们就可以知道,其实coremark 就是跑个程序n 循环,然后计算一个 指令/时间/频率 这样的结果,所以我们移植只需要给出以下几个参数
-
时间获取方式,start_time() 和 stop_time()向里追,最后会有时间函数的实现,这里一般获取的都是cnt 数,需要结合自己的硬件定时器来实现这个函数,这里只是获取了计数值,没有考虑时钟频率的影响。
-
CLOCKS_PER_SEC 这个宏定义改为你的时钟频率,第一点的获取了这段时间内增加的cnt值,这里有了时间周期,那么
time_in_secs(total_time)
这个函数就能够计算出执行当前的时间了。其实最后也是cnt 值/频率=时间
-
iterations ,结合时钟频率不同,需要保证coremark 跑10s 以上,即
time_in_secs(total_time)
计算出来的结果是10s 以上,按照实际的结果给一个值就可以了。 -
printf 的实现,需要根据实际情况注意是不是要加printf这个宏
//如果编译的时候加上了 -DHAS_PRINTF,那么这里就不会生效,但是还是代表了HAS_PRINTF #ifndef HAS_PRINTF #define HAS_PRINTF 1 #endif //由于coremark 都是使用的ee_printf,所以需要把ee_printf符号替换为printf #if HAS_PRINTF #define ee_printf printf #endif 以上就是移植的要点,需要哪些文件内容官网readme 有说,就不赘述了。
2. dhrystone
2.1 dhrystone 计算方式
和coremark 类似,dhrystone的主函数也是进行算 跑dhrystone 程序的时间,以推出来单位时间下跑dhrystone 的个数,再除以MHZ的话就可以推出来 再1MHZ的情况下,1秒能跑多少dhrystone 程序。
主题程序如下:
/***************/ /* Start timer */ /***************/ #ifdef TIMES times (&time_info); Begin_Time = (long) time_info.tms_utime; #endif #ifdef TIME Begin_Time = time ( (long *) 0); #endif #ifdef MSC_CLOCK Begin_Time = clock(); #endif for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) { Proc_5(); Proc_4(); /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */ Int_1_Loc = 2; Int_2_Loc = 3; strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING"); Enum_Loc = Ident_2; Bool_Glob = ! Func_2 (Str_1_Loc, Str_2_Loc); /* Bool_Glob == 1 */ while (Int_1_Loc < Int_2_Loc) /* loop body executed once */ { Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc; /* Int_3_Loc == 7 */ Proc_7 (Int_1_Loc, Int_2_Loc, &Int_3_Loc); /* Int_3_Loc == 7 */ Int_1_Loc += 1; } /* while */ /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ Proc_8 (Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc); /* Int_Glob == 5 */ Proc_1 (Ptr_Glob); for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) /* loop body executed twice */ { if (Enum_Loc == Func_1 (Ch_Index, 'C')) /* then, not executed */ { Proc_6 (Ident_1, &Enum_Loc); strcpy (Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING"); Int_2_Loc = Run_Index; Int_Glob = Run_Index; } } /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */ Int_2_Loc = Int_2_Loc * Int_1_Loc; Int_1_Loc = Int_2_Loc / Int_3_Loc; Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc; /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */ Proc_2 (&Int_1_Loc); /* Int_1_Loc == 5 */ } /* loop "for Run_Index" */ /**************/ /* Stop timer */ /**************/ #ifdef TIMES times (&time_info); End_Time = (long) time_info.tms_utime; #endif #ifdef TIME End_Time = time ( (long *) 0); #endif #ifdef MSC_CLOCK End_Time = clock(); #endif
以上就可以通过Begin_Time
和End_Time
获取运行程序的时间,在有以下的计算程序:
User_Time = End_Time - Begin_Time; #ifdef TIME /*User_Time 已经是具体时间计数了*/ Microseconds = (float) User_Time * Mic_secs_Per_Second / (float) Number_Of_Runs; Dhrystones_Per_Second = (float) Number_Of_Runs / (float) User_Time; #else /*User_Time 是counter值*/ Microseconds = (float) User_Time * Mic_secs_Per_Second / ((float) HZ * ((float) Number_Of_Runs)); Dhrystones_Per_Second = ((float) HZ * (float) Number_Of_Runs) / (float) User_Time; #endif
以user_time 是counter值为例:Dhrystones_Per_Second =Number_Of_Runs ÷ 时间 = Number_Of_Runs÷ (counter/频率)
,于是就有了上面的公式。
对于一般的DMIP_MHZ,上面的结果还需要再除以一个频率,因为是xMhz 跑的,不是1Mhz 跑的。即
DMIP_MHZ = Dhrystones_Per_Second ÷(频率/1Mhz)
例如 Dhrystones_Per_Second 为12,主频为5Mhz,那么结果就为12/5 = 2.4.
2.2 dhrystone 移植要点
理解了第一点,这里就比较简单,其实和coremark 一样。只需要做好以下两点就可以了:
- 提供时间基准,用于获取start time 和 end time ,一般为timer 的计数器。
- 提供pintf 函数的重定义,用于打印。
- 注意不要让计数器超过计数范围了。
本文作者:Satellite98
本文链接:https://www.cnblogs.com/satellite98/p/18041458
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步