什么是CoreMark?
来自CoreMark首页的解释是:
CoreMark is a simple, yet sophisticated benchmark that is designed specifically to test the functionality of a processor core. Running CoreMark produces a single-number score allowing users to make quick comparisons between processors.
翻译一下就是:
CoreMark是一个简单而又精密的基准测试程序,是专门为测试处理器核功能而设计的。运行CoreMark会产生一个“单个数字”的分数,(从而)允许用户在(不同)CPU之间进行快速比较。
简单来说,就是一个测试CPU性能的程序,类似PC上的Cinebench、CPU-Z之类的CPU性能测试工具。
了解了CoreMark是什么之后,接下来我们尝试在龙芯2K0500先锋板上跑一下CoreMark,看看分数是多少。
在Linux编译主机上,执行如下命令,将CoreMark源码下载到本地:
git clone https://github.com/eembc/coremark.git
下载完成后,可以看到有这些文件和目录:
接着编译CoreMark,这里假设你已经正确设置了龙芯交叉编译工具链,也就是可以直接运行loongarch64-linux-gnu-gcc命令。
在Linux编译主机上,执行如下命令:
cd coremark
make CC=loongarch64-linux-gnu-gcc link
其中:
编译完成后,可以看到生成了coremark.exe:
通过FTP或U盘,将coremark.exe拷贝到龙芯2K0500先锋板上,使用如下命令运行coremark.exe:
# 添加可执行权限
chmod +x coremark.exe
# 运行
./coremark.exe
运行结束后,输出如下:
可以看到,龙芯2K0500上CoreMark跑分为2213.205459分。
我这里测试使用的树莓派3B+开发板,系统版本信息是:
由于树莓派3B+上运行的是Debian系统,有完整的编译工具链。因此,在树莓派3B+上,我们可以直接在开发板上编译源码。
在树莓派3B+上运行CoreMark之前,也需要下载CoreMark源码,和前面类似:
git clone https://github.com/eembc/coremark.git
不过这次我们直接将CoreMark源码下载到了树莓派上。
树莓派上编译CoreMark之前,需要先安装编译构建工具链,如果还没有的话,可以使用如下命令:
sudo apt install build-essential
PS:如果已经有gcc、make命令,则可以跳过此步骤。
使用如下命令,编译CoreMark源码:
cd coremark
make link
使用如下命令运行coremark.exe:
./coremark.exe
PS:这里由于我们是直接在树莓派3B+开发板上编译的CoreMark,所以直接运行即可。
运行结束后,输出如下:
可以看到,树莓派3B+上CoreMark跑分为1914.486280。
龙芯2K0500和树莓派3B+的CoreMark跑分对比:
龙芯2K0500 | 树莓派3B+ | |
---|---|---|
跑分 | 2213.205459 | 1914.486280 |
可以看到,龙芯2K0500上的CoreMark跑分高于树莓派3B+。
查看CoreMark的Makefile和相关源码,我们可以知道,通过编译时添加XCFLAGS参数,可以指定CoreMark的编译参数。
下面是几组不同XCFLAGS参数下,龙芯2K0500和树莓派3B+的CoreMark跑分:
XCFLAGS | 龙芯2K0500 | 树莓派3B+ |
---|---|---|
2213.205459 | 1914.486280 | |
"-DPERFORMANCE_RUN=1" | 2213.532059 | 1916.198263 |
"-DPERFORMANCE_RUN=1 MEM_METHOD=MEM_STACK" | 2218.278616 | 1915.219612 |
"-DPERFORMANCE_RUN=1 MEM_METHOD=MEM_STATIC" | 2216.475803 | 1916.687963 |
可以看到,几种不同XCFLAGS参数条件下,龙芯2K0500上的CoreMark跑分都要高于树莓派3B+。
添加XFLAGS参数后,树莓派上的编译命令为(以表格最后一行参数为例):
make XCFLAGS="-DPERFORMANCE_RUN=1 -DMEM_METHOD=MEM_STATIC" link
响应的,Linux编译服务器上,交叉编译命令为:
make CC=loongarch64-linux-gnu-gcc XCFLAGS="-DPERFORMANCE_RUN=1 -DMEM_METHOD=MEM_STATIC" link
CoreMark项目README的Key Algorithms描述了CoreMark主要用到了那些算法:
说明在这几种计算场景下,龙芯2K0500的速度都是比树莓派3B+要快的。
接下来我们看看另外一种场景下的测试结果。
我们知道,生成一个较大的大质数,或者判断一个大整数是否为质数是比较复杂的。
所以,这里我们准备用生成质数在两个开发板上再次进行测试。
我们使用如下C程序代码,计算第n个质数:
#include <time.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include <inttypes.h>
// 判断n是否为质数
bool isprime(uint64_t n)
{
assert(n > 0);
if (n == 2) return true;
if ((n % 2) == 0) return false;
for (uint64_t i = 3, up = n / 2; i < up; i += 2) {
if (n % i == 0) {
return false;
}
}
return true;
}
// 计算第n个质数,例如:1 => 2, 2 => 3, 3 => 5
uint64_t prime(int n)
{
assert(n > 0);
if (n == 1) return 2;
int count = 1;
for (uint64_t i = 3; i < UINT64_MAX; i += 2) {
if (isprime(i)) {
if (++count == n) {
return i;
}
}
}
return 0;
}
int main(int argc, char* argv[])
{
int n = argc > 1 ? atoi(argv[1]) : 10;
clock_t start = clock();
uint64_t prim = prime(n);
clock_t end = clock();
float costs = (end - start) / (float) CLOCKS_PER_SEC;
printf("%10d\t%.6f\t%" PRIu64 "\n", n, costs, prim);
return 0;
}
这里为了忽略两块开发板内存差异的影响,我们不保存前面得到的质数(虽然保存前面得到的质数,可以加速后续的isprime判断)。
这里假设保存的文件名为p1.c,树莓派3B+上使用如下命令编译:
gcc -O2 -o p1 p1.c
Linux编译主机上,使用如下命令交叉编译:
loongarch64-linux-gnu-gcc -O2 -o p1 p1.c
接下来,分别在龙芯2K0500和树莓派3B+上运行,得到如下耗时数据(编译选项:-O2):
n | 龙芯2K0500耗时 | 树莓派3B+耗时 |
---|---|---|
1000 | 0.018571 | 0.014308 |
2000 | 0.080962 | 0.061902 |
3000 | 0.191983 | 0.146851 |
4000 | 0.353578 | 0.271425 |
5000 | 0.567774 | 0.435833 |
6000 | 0.831575 | 0.640650 |
7000 | 1.153037 | 0.890962 |
8000 | 1.533347 | 1.172405 |
9000 | 1.965950 | 1.517557 |
这里得到的结论是——树莓派3B+计算质数更快。此前的TFLM测试结果和这里比较类似,同样显示,龙芯2K0500成绩要稍差一些。
这里龙芯2K500比树莓派3B+慢的主要原因,很可能是因为求质数算法过程中包含了大量除法运算,而龙芯2K0500的除法运算速度要比树莓派3B+慢。
验证方法也很简单,我们可以直接修改前面的isprime函数:
// 判断n是否为质数
bool isprime(uint64_t n)
{
assert(n > 0);
if (n == 2) return true;
if ((n & 1) == 0) return false; // n % 2 => n & 0x1
for (uint64_t i = 3, up = (n >> 1); i < up; i += 2) { // n / 2 => n >> 1
for (uint64_t j = 3; j < up; j += 2) { // 暴力枚举另外一个因数,不用除法
if (i * j == n) {
return false;
}
}
}
return true;
}
这里假设保存的文件名为p2.c,树莓派3B+上使用如下命令编译:
gcc -O2 -o p2 p2.c
Linux编译主机上,使用如下命令交叉编译:
loongarch64-linux-gnu-gcc -O2 -o p1 p1.c
接下来,分别在龙芯2K0500和树莓派3B+上运行,得到如下耗时数据(编译选项:-O2):
n | 龙芯2K0500耗时 | 树莓派3B+耗时 |
---|---|---|
400 | 0.293424 | 0.302985 |
500 | 0.616077 | 0.634836 |
600 | 1.123482 | 1.162557 |
这里可以看到,龙芯2K500比树莓派3B+计算要快。
所以,这里验证了前面的猜想——龙芯2K500比树莓派3B+的整数除法要慢。
更多回帖