搜索
bottom↓
回复: 34

【学习笔记四】原创申精,欢乐的比较KEIL、IAR、CW数据拷贝

[复制链接]

出0入0汤圆

发表于 2014-9-14 21:31:43 | 显示全部楼层 |阅读模式
本帖最后由 sunnyqd 于 2014-9-14 21:55 编辑

终于搞好了IAR和CW平台的配置
KEIL编译器为ARMCC
IAR编译器为IAR C/C++ Compiler for ARM
CW编译器为GNU C Compiler
据说KDS也为GNU C Compiler,那这里就不列出KDS了
以上三个平台采用速度最大优化,禁止内联

这只是一个简短的比较,难免有疏漏之处,只供参考

比较的函数为默认的库函数里的memcpy()和如下的函数

  1. void intmemcpy(int32_t* dest, const int32_t* src,  const int32_t size)
  2. {
  3.   int32_t i;
  4.   for(i=0;i<size;i++)
  5.   {
  6.     dest[i] = src[i];
  7.   }
  8. }
  9. void intmemcpy2(int32_t* dest, const int32_t* src,  int32_t size)
  10. {
  11.   while(size--)
  12.   {
  13.     dest[size]=src[size];
  14.   }
  15. }
  16. void intmemcpy3(int32_t* dest, const int32_t* src,  uint32_t size)
  17. {
  18.   while(size--)
  19.   {
  20.     dest[size]=src[size];
  21.   }
  22. }
  23. void intmemcpy4(int32_t* dest, const int32_t* src,  const int32_t size)
  24. {
  25.   int32_t i;
  26.   for(i=0;i<size;i++)
  27.   {
  28.     *dest++ = *src++;
  29.   }
  30. }
  31. void charmemcpy(char* dest, const char* src, const int32_t size)
  32. {
  33.   int32_t i;
  34.   for(i=0;i<size;i++)
  35.   {
  36.     dest[i] = src[i];
  37.   }
  38. }
  39. void duffcpy(uint32_t* dest, const uint32_t* src, const uint32_t size)
  40. {
  41.   uint32_t n = (size + 7u) >>3;
  42.   switch (size % 8)
  43.   {
  44.       case 0:    do { *dest++ = *src++;
  45.       case 7:     *dest++ = *src++;
  46.       case 6:     *dest++ = *src++;
  47.       case 5:     *dest++ = *src++;
  48.       case 4:     *dest++ = *src++;
  49.       case 3:     *dest++ = *src++;
  50.       case 2:     *dest++ = *src++;
  51.       case 1:     *dest++ = *src++;
  52.       } while (--n > 0);
  53.   }
  54. }
  55. void duffcpy2(uint32_t* dest, const uint32_t* src, const uint32_t size)
  56. {
  57.   uint32_t n = (size + 7u) >>3;
  58.   uint32_t i = 0;
  59.   switch (size % 8)
  60.   {
  61.       case 0:    do { *dest++ = *src++;
  62.       case 7:     *dest++ = *src++;
  63.       case 6:     *dest++ = *src++;
  64.       case 5:     *dest++ = *src++;
  65.       case 4:     *dest++ = *src++;
  66.       case 3:     *dest++ = *src++;
  67.       case 2:     *dest++ = *src++;
  68.       case 1:     *dest++ = *src++;
  69.       } while (++i < n);
  70.   }
  71. }
复制代码

测试数据为
  1. int32_t Buf0[101];\\放置在0x20000800;
  2. int32_t Buf1[101];\\放置在0x20000A00;
  3. int32_t Buf2[101];\\放置在0x1FFFFD00;
  4. const int32_t Buf3[101];\\放置在0xF410;
复制代码


平台配置为:
KEIL:
IAR:
CW:

这里插上一句,虽然选择了CW里的do not inline,但是编译后还是被inline,无奈,只好将上述函数放到另一个文件里才解决

以下为测试结果
KEIL:
IAR:
CW:

很有意思的结果,KEIL和IAR的速度分布比较类似,自带库memcpy的效率最高,其中IAR的memcpy最快为356个时钟周期
但是CW的结果很难令人理解自带memcpy速度最慢,而charmemcpy函数居然比intmemcpy函数快,也就是分单字节拷贝比用int拷贝的速度快,很奇怪
下面是部分分析

KEIL默认的memcpy为

IAR默认的memcpy为

按结果来,IAR更快一点

CW默认的memcpy速度慢的原因可能是与它的使用的库有关,这个memcpy默认使用了一个.c文件里的内容,反汇编为


难怪CW你这么慢呢。。。。我尝试了宏_EMBEDDED_WARRIOR_MEMFUNCS,但是看反汇编的结果不起作用,无语,对你失望了

CW的charmemcpy被编译成了好长的一段,如下



无语

继续,Keil下的intmemcpy为

IAR的intmemcpy为

可见IAR将循环展开了许多,这么卖力,难怪比Keil快

但是,对于duffcopy
Keil为

IAR为

CW为


KEIL和CW都比较老实的用了STM和LDM
IAR难怪这里你最慢了

按着三个平台搭建项目的体会是,Keil最简便,搭建的过程中没有任何问题,CW问题最多,需要手动更改好几个地方才可以
可能是与我Keil用的比较多也有一定的关系

按操作体验来说,Keil最便捷,CW最繁琐,IAR居中

按界面来看,IAR最简洁,但是比较难看,Keil居中,CW虽然在eclipse下面比较华丽,但是相对来说臃肿一些

所以对于Cortex我还是喜欢选择Keil,其次IAR,但不会选择使用CW,(KDS可能与CW类似,但是免费的,这是优势)

编辑原因:补充图片

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)

出0入0汤圆

发表于 2014-9-14 21:50:07 | 显示全部楼层
很有意思的测试,问一下,这个Ticks计数是如何实现的?

出0入0汤圆

 楼主| 发表于 2014-9-14 21:51:10 | 显示全部楼层
上面结果还可以发现一个有趣的现象
对于四个intmemcpy函数,均是intmemcpy和intmemcpy4的写法是最快的
对于
Keil:intmemcpy和intmemcpy4一样的速度
IAR:  intmemcpy4较intmemcpy快
CW:intmemcpy较intmemcpy4快

其中IAR的intmemcpy4最快

出0入0汤圆

 楼主| 发表于 2014-9-14 21:53:32 | 显示全部楼层
浪里白条 发表于 2014-9-14 21:50
很有意思的测试,问一下,这个Ticks计数是如何实现的?

看我上一个帖子,http://www.amobbs.com/forum.php? ... p;extra=#pid7890315
使用systick,里面有说tick的获取方式是tick1-tick2-(tick0-tick1),其中(tick0-tick1)是调用systick函数时的开销

出100入101汤圆

发表于 2014-9-14 21:55:26 | 显示全部楼层
学习了。通过lz的分析,对汇编有了感性的认识。

出0入0汤圆

发表于 2014-9-14 22:00:40 | 显示全部楼层
查了下汇编手册,没看懂这俩的区别



寻址方式不一样?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2014-9-14 22:01:50 | 显示全部楼层
浪里白条 发表于 2014-9-14 22:00
查了下汇编手册,没看懂这俩的区别

一个可以一条指令加载多个寄存器,一个是只加载一个,M是multiple的意思

出0入0汤圆

发表于 2014-9-14 22:05:49 | 显示全部楼层
确实keil虽然在界面上没有eclipse上好看,但是真的受不了eclipse的臃肿。可能跟我的电脑有关,难道要换了?

出0入0汤圆

发表于 2014-9-14 22:06:31 | 显示全部楼层
CW和KEIL很傻,intmemcpy2和intmemcpy3中一个size-- 都不知道优化下。

出0入0汤圆

发表于 2014-9-14 22:08:33 | 显示全部楼层
sunnyqd 发表于 2014-9-14 22:01
一个可以一条指令加载多个寄存器,一个是只加载一个,M是multiple的意思

字面意思能理解,为何会对速度造成影响呢?

出0入0汤圆

发表于 2014-9-14 22:09:01 | 显示全部楼层
又涨见识了!!!

出0入0汤圆

 楼主| 发表于 2014-9-14 22:09:41 | 显示全部楼层
浪里白条 发表于 2014-9-14 22:06
CW和KEIL很傻,intmemcpy2和intmemcpy3中一个size-- 都不知道优化下。

一个是uint,一个是int,keil里面可能考虑到输入是负数时的情况,分别处理

出0入0汤圆

 楼主| 发表于 2014-9-14 22:11:16 | 显示全部楼层
浪里白条 发表于 2014-9-14 22:08
字面意思能理解,为何会对速度造成影响呢?

这需要看详细的架构或指令手册了,LDM的特点是,加载完之后,可以自增

出0入0汤圆

发表于 2014-9-14 22:13:39 | 显示全部楼层
sunnyqd 发表于 2014-9-14 22:11
这需要看详细的架构或指令手册了,LDM的特点是,加载完之后,可以自增

果然,看了下配图IAR有2个ADD

出0入0汤圆

发表于 2014-9-14 22:41:31 | 显示全部楼层
有意思!表示一直用Keil

出0入0汤圆

发表于 2014-9-15 07:40:52 来自手机 | 显示全部楼层
lz有心人,这个比较研究很有意思。for, while, signed, unsigned这些的差异是对c语言的比较深入研究。

出0入0汤圆

发表于 2014-9-15 08:00:11 | 显示全部楼层
还是对GNU C Compiler 比较熟悉些 ,但是没用过CW 。看到了底层的汇编,头大

出0入0汤圆

发表于 2014-9-15 08:11:05 | 显示全部楼层
长见识了!         

出0入0汤圆

发表于 2014-9-15 08:52:44 | 显示全部楼层
其实对照不同的编译器,观察语句和汇编,会发现有很大不同。如果经常分析C和汇编,就能写出优化程度高的C语言。当然得针对不同的编译器。
所以也建议不要经常更换编译器,毕竟用熟悉的环境能避免很多BUG.

出0入0汤圆

发表于 2014-9-15 09:09:25 | 显示全部楼层
sunnyqd 发表于 2014-9-14 22:09
一个是uint,一个是int,keil里面可能考虑到输入是负数时的情况,分别处理

uint和int为什么要分别处理?不是都按32位来处理么,对MCU来说应该没什么区别呀

出0入0汤圆

 楼主| 发表于 2014-9-15 09:34:47 | 显示全部楼层
zhengxg1990 发表于 2014-9-15 09:09
uint和int为什么要分别处理?不是都按32位来处理么,对MCU来说应该没什么区别呀 ...

同样为0xFFFFFFF,一个是最大,一个是负1,与0判断的时候,明显不一样

出0入0汤圆

发表于 2014-9-15 14:42:57 | 显示全部楼层
sunnyqd 发表于 2014-9-15 09:34
同样为0xFFFFFFF,一个是最大,一个是负1,与0判断的时候,明显不一样

不是比的数据拷贝么

出0入17汤圆

发表于 2014-9-15 16:06:14 | 显示全部楼层
arm有专门的memcpy指令吧

出0入0汤圆

发表于 2014-9-15 19:38:37 | 显示全部楼层
又学习了哇

出0入0汤圆

发表于 2014-9-15 21:12:14 | 显示全部楼层
长知识了。

出0入0汤圆

发表于 2014-9-16 09:19:50 | 显示全部楼层
楼主。辛苦了。

出10入0汤圆

发表于 2014-9-20 12:16:36 | 显示全部楼层
这个很有参考价值!!mark!!

出0入0汤圆

发表于 2014-9-20 12:39:27 | 显示全部楼层
很好!谢谢!

出0入0汤圆

发表于 2014-9-20 12:49:59 | 显示全部楼层
很好,mark

出0入0汤圆

发表于 2014-9-20 12:50:50 | 显示全部楼层
欢乐的顶一下,学习了

出0入0汤圆

发表于 2014-9-20 13:00:24 | 显示全部楼层
学习了。

出0入0汤圆

发表于 2014-9-22 11:45:52 | 显示全部楼层
实战项目中,我用IAR较多。。。

出0入0汤圆

发表于 2014-9-23 10:12:02 | 显示全部楼层
楼主这一对比,很多用Keil的人找到了用它的理由了。

出0入0汤圆

发表于 2014-9-23 11:21:55 | 显示全部楼层
楼主牛X,这个对比很详细,很有说服性。
考虑是不是要换到KEIl上去。CW太麻烦了。

出0入0汤圆

发表于 2014-9-26 16:17:54 来自手机 | 显示全部楼层
mark           .
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-23 09:24

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表