当前时区为 UTC + 8 小时



发表新帖 回复这个主题  [ 4 篇帖子 ] 
作者 内容
1 楼 
 文章标题 : 为何这个C程序写内存比读内存更快?
帖子发表于 : 2017-07-26 20:48 

注册: 2013-05-26 6:58
帖子: 2076
系统: Debian 9
送出感谢: 867
接收感谢: 27
为何这个C程序写内存比读内存更快?
代码:
//usage:
//./a.out max r/w repeat timeout
//indent ./zramtest.c;gcc -O0 ./zramtest.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int
main (int argc, char **argv)
{
  time_t const start_time = time (NULL);
  time_t timeout;
  int max;
  int repeat;
  if (argc == 5)
    {
      max = atoi (argv[1]);
      repeat = atoi (argv[3]);
      timeout = ((time_t) (atoi (argv[4])));
    }
  else
    return 1;

  unsigned char **block_array =
    calloc (sizeof (unsigned char *), (size_t) (max));

  size_t block_length = (size_t) (1024u * 1024u);

  unsigned char data[3];
  data[0] = 'a';
  data[1] = 'b';
  data[2] = 'c';

  unsigned i = 0u;
  //initialize block_array
  for (i = 0u; i < max; i++)
    {
      do
   {
     if ((timeout > ((time_t) (0)))
         && ((time (NULL) - start_time) > timeout))
       {
         puts ("timeouted!");
         return 0;
       }
     block_array[i] = malloc (block_length);
     if (block_array[i] != NULL)
       {
         unsigned bi = 0u;
         for (bi = 0u; bi < block_length; bi++)
      block_array[i][bi] = data[bi % ((unsigned) (sizeof (data)))];
       }
     else
       {
         printf ("%u error\n", i);
       }
   }
      while (NULL == block_array[i]);
    }
  puts ("init ok");

  unsigned score = 0u;
//do page read test
  if ('r' == argv[2][0])
    for (;;)
      {
   for (i = 0u; i < max; i++)
     {
       if ((timeout > ((time_t) (0)))
      && ((time (NULL) - start_time) > timeout))
         {
      puts ("timeouted!");
      goto show_score;
         }

       unsigned bi = 0u;
       for (bi = 0u; bi < block_length; bi++)
         {
      data[bi % ((unsigned) (sizeof (data)))] = block_array[i][bi];
         }
       score++;
     }
   if (repeat >= 0)
     {
       repeat--;
       if (0 == repeat)
         goto show_score;
     }
      }
//do page write test
  else if ('w' == argv[2][0])
    for (;;)
      {
   for (i = 0u; i < max; i++)
     {
       if ((timeout > ((time_t) (0)))
      && ((time (NULL) - start_time) > timeout))
         {
      puts ("timeouted!");
      goto show_score;
         }

       unsigned bi = 0u;
       for (bi = 0u; bi < block_length; bi++)
         {
      block_array[i][bi] = data[bi % ((unsigned) (sizeof (data)))];
         }
       score++;
     }
   if (repeat >= 0)
     {
       repeat--;
       if (0 == repeat)
         goto show_score;
     }
      }
show_score:
  printf ("score:%u\n", score);
  return 0;
}


为了保持客观,我测试的时候没有任何swap设备,zram模块也是卸载掉的.

测试结果:
代码:
$ time ./a.out 100 r  5 -1
init ok
score:500

real   0m2.692s
user   0m2.592s
sys   0m0.096s
$ time ./a.out 100 w  5 -1
init ok
score:500

real   0m2.566s
user   0m2.468s
sys   0m0.096s
$ time ./a.out 100 r  5 -1
init ok
score:500

real   0m2.691s
user   0m2.608s
sys   0m0.080s
$ time ./a.out 100 w  5 -1
init ok
score:500

real   0m2.571s
user   0m2.468s
sys   0m0.100s
$ time ./a.out 100 r  5 -1
init ok
score:500

real   0m2.698s
user   0m2.608s
sys   0m0.088s
$ time ./a.out 100 w  5 -1
init ok
score:500

real   0m2.566s
user   0m2.476s
sys   0m0.092s
$


_________________
Linux桌面优化综合贴[2017.09.18](欢迎各位补充或指正误区)
[2016.03.10]会C语言但看不懂英文文档的点这里,一个用C语言编写的简陋学习工具
单硬盘通过iso文件实机安装Debian的方法
重启或操作fcitx时失去响应的一个解决方法,不妨试试看


页首
 用户资料  
 
2 楼 
 文章标题 : Re: 为何这个C程序写内存比读内存更快?
帖子发表于 : 2017-07-27 17:55 
头像

注册: 2008-09-18 13:11
帖子: 2694
送出感谢: 1
接收感谢: 437
你这个只是在比 读堆写栈 和 读栈写堆 谁快。堆和栈都是内存,完全不是你以为的是在比 写内存 和 读内存
block_array在堆上,data在栈上,访问栈上的数据可以直接栈寄存器加偏移,理论上会比通过内存地址访问堆快一丁点。另外还因为现代CPU有流水线以及相关的优化手段存在,代码顺序的差异可能会导致执行时间差异被进一步放大。

我自己做了个测试,把
代码:
block_array[i][bi] = data[bi % ((unsigned) (sizeof (data)))];

改成
代码:
p = &block_array[i][bi];
q = &data[bi % ((unsigned) (sizeof (data)))];
*p = *q;

这种形式,这样两种赋值只有*p = *q和*q = *p的差别了,最终产生的机器码除开地址以外是完全一致的。这样可以尽可能减少流水线机制的干扰

在服务器的E5-2603 v2 CPU上跑测试,测出来的结果如下
1. 同样往变量中读(c = *p 和 c = *q ),从栈读比从堆读快了4%
2. 同样写入立即数(*p = 1 和 *q = 1 ),往栈写比往堆写快了1%
3. 按你的代码逻辑(*p = *q 和 *q = *p),读堆写栈 比 读栈写堆 慢了1.5%



_________________
评价: 3.7% 科学之子
 
页首
 用户资料  
 
3 楼 
 文章标题 : Re: 为何这个C程序写内存比读内存更快?
帖子发表于 : 2017-07-28 21:58 

注册: 2013-05-26 6:58
帖子: 2076
系统: Debian 9
送出感谢: 867
接收感谢: 27
astolia 写道:
block_array在堆上,data在栈上,访问栈上的数据可以直接栈寄存器加偏移,理论上会比通过内存地址访问堆快一丁点。

您说的"访问"指的是"读"还是"写"?
@astolia


_________________
Linux桌面优化综合贴[2017.09.18](欢迎各位补充或指正误区)
[2016.03.10]会C语言但看不懂英文文档的点这里,一个用C语言编写的简陋学习工具
单硬盘通过iso文件实机安装Debian的方法
重启或操作fcitx时失去响应的一个解决方法,不妨试试看


页首
 用户资料  
 
4 楼 
 文章标题 : Re: 为何这个C程序写内存比读内存更快?
帖子发表于 : 2017-08-01 22:41 
头像

注册: 2008-09-18 13:11
帖子: 2694
送出感谢: 1
接收感谢: 437
我指的是CPU的内存寻址。不过你这个测试程序里既有堆也有栈,对最后结果倒是不会有影响


页首
 用户资料  
 
显示帖子 :  排序  
发表新帖 回复这个主题  [ 4 篇帖子 ] 

当前时区为 UTC + 8 小时


在线用户

正在浏览此版面的用户:没有注册用户 和 2 位游客


不能 在这个版面发表主题
不能 在这个版面回复主题
不能 在这个版面编辑帖子
不能 在这个版面删除帖子
不能 在这个版面提交附件

前往 :  
本站点为公益性站点,用于推广开源自由软件,由 DiaHosting VPSBudgetVM VPS 提供服务。
我们认为:软件应可免费取得,软件工具在各种语言环境下皆可使用,且不会有任何功能上的差异;
人们应有定制和修改软件的自由,且方式不受限制,只要他们自认为合适。

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
简体中文语系由 王笑宇 翻译