精彩教程:快速初始化内存(1)
许多计算密集型的应用都需要处理大量内存,这种应用中的内存初始化是一个常规操作,而内存和cpu内部的数据交换之间的速度瓶颈决定了内存初始化将会占用可观的时间。但因为应用程序初始化内存往往调用crt的memset或者windows api的zeromemory,很少有人在初始化方面进行优化。
另一方面,现在的应用硬件一般配置都比较好,大部分应用都运行在pii之上,但我们在使用诸如vc之类的编译环境时往往选择速度优化,并选择合适的处理器,然后寄希望于编译器给我们生成优化的结果,结果往往发现并不如意。
在我们的一个图像处理项目中,需要大量内存操作,而且多个线程同时运行,内存存取成为了各个模块的竞争资源,所以对内存存取优化成为项目的关键。在努力减少内存操作遍数的基础上,加快内存初始化成为我们的改进重点。
在用vc各种手段都没有太多改进后,我们把目光转向处理器特征。从pentium系列开始,一方面intel在不断提高cpu主频,同时也在针对多媒体等应用相继推出mmx/sse/sse2,增加了许多多位快速处理指令。在高层语言方面,intel的c++ compiler提供了针对不同处理器的最优化结果。但在一个成熟项目中贸然使用另外一种编译环境的风险较大,所以我们从intel环境中抽取了memset的实现,重新组织了一个lib,并在我们的项目中针对内存初始化进行了改动,并链接到抽取的lib库中。在内存初始化方面有了一个较大的提高。
下面我们用测试例子说明该过程。
一个例子
在测试程序中,分别调用微软c库的memset和intel版本的memset分别对100m内存进行60遍初始化,,为了模拟多线程环境,启动了两个线程同时进行内存初始化。测试时使用了release版,为了方面查看包含了调试信息(调试信息无影响)。测试结果:
msc 版本:12.453~12.547秒
intel c版本:4.375~4.531秒
可见在大量内存操作时差别比较大。对内存存取密集型项目,因为内存存取往往是瓶颈,应该还可以提高整体处理性能。
下面是例子的代码:
// 本程序示例了使用微软crt的memset和intel优化的memset初始化内存的速度差异
// lihw.
#include
#include
#include
extern "c"
void * __cdecl __intel_new_memset(void *, int, size_t);
#pragma comment(lib,"intelmem.lib")
#define size 1024*1024*100
void threadfunc(void *dummy)
{
lpbyte lpbyte = (lpbyte)dummy;//new byte[size];
int j;
#define looptimes 60
dword dwstart, dwtime1,dwtime2;
//
//intel version
dwstart = gettickcount();
for (j=0; j< looptimes; j++)
{
__intel_new_memset(lpbyte,1,size);
}
dwtime1 = gettickcount() - dwstart;
//ms crt version
dwstart = gettickcount();
for (j=0; j< looptimes; j++)
{
memset(lpbyte,1,size);
//zeromemory(lpbyte,size);
}
dwtime2 = gettickcount() - dwstart;
//delete []lpbyte;
printf("intel=%dms msc=%dms\n",dwtime1,dwtime2);
}
int main(int argc, char* argv[])
{
#define threads 2
handle hthread[threads]; //array to hold thread handle
lpbyte lpbyte[threads]; //array to hold thread-specific memory
int i;
//count mem alloc time. debug version is very long
dword dwstart = gettickcount();
for (i=0; i
{
lpbyte[i] = new byte[size];
}
printf("alloc spend=%d\n",gettickcount() - dwstart);
//start thread
for (i=0; i
hthread[i] = (handle)_beginthread( threadfunc, 0, lpbyte[i] );
//threadfunc(lpbyte[i]);
waitformultipleobjects(threads,hthread,true,infinite);
for (i=0; i
delete []lpbyte[i];
printf("process exec time=%dms\n",gettickcount() - dwstart);
return 0;
}
让我们来看看究竟上什么造成这么大的差别。在release版本的__intel_new_memset处和memset处设置断点,打开反汇编窗口:
intel版本:
31: for (j=0; j< looptimes; j++)
32: {
33: __intel_new_memset(lpbyte,1,size);
00401017 push 6400000h
0040101c push 1
0040101e push ebx
0040101f call ___intel_new_memset (00401110)
00401024 add esp,0ch
00401027 dec esi
00401028 jne threadfunc+17h (00401017)
34: }
()
- · Jave基础学习:jdbc小技巧
- · 一棵php的类树(支持无限分类)
- · 用asp.net 实现九连环小游戏
- · MySQL数据导入导出方法与工具介绍(1)
- · 轻松弹出无边框网页的Javscrpt代码
- · ASP初学者参考
- · Java新手学习:IIS6和Tomcat5的整合
- · asp常用函数
- · W3 Jmail中文使用说明
- · 无组件上传图片到数据库中,最完整解决方案
- · 二级域名原理以及程序,申请即可开通
- · Java学习过程的一些重点
- · Oracle9i中如何建立不同字符集的数据库
- · 修复SQL Server 2000数据库之实战经验
- · 使用ASP生成HTML文件
- · 编写安全的ASP代码
- · 十天学会ASP.net(2)
- · 十天学会ASP.net(1)
- · 十天学会php(2)
- · 十天学会php(1)
- · 三天学好ADO
- · 在数据库中存取文件
- · 解决大字段在Form中Post出错的方法
- · 利用ASP+JMAIL进行邮件群发的新思路
- · 关于处理GET方式提交的含有特殊字符的参数
- · 关于Adodb.Stream 的使用说明
- · 多文件多文本框上传程序
- · 让妙客家标准版使用 SQL Server 数据库后台
- · 关于用SQL SERVER2000建立分布式网站系统的认识
- · 使用SQLSERVER的扩展存储过程实现远程备份与恢复
- · MySQL数据库类的定义
- · SQL语句导入导出大全
- · SQL Server的用户及权限
- · 深入理解C语言指针的奥秘
- · VC快捷键大全
- · 简体中文编码对应器
- · WEB打印大全
- · 用ASP实现远程批量文件改名
