博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
深入探讨用位掩码代替分支(4):VC2010速度测试
阅读量:6964 次
发布时间:2019-06-27

本文共 4122 字,大约阅读时间需要 13 分钟。

  前面我们用VC6测试了位掩码代替分支的速度。VC6是1998年发售的,离现在有14年了。在14年里,Intel与AMD的CPU都换了好几套微架构了,VC6编译器很可能无法充分发挥它们的性能。而且,从2003年AMD推出了64位处理器开始,现在64位系统越来越普及,我们希望测试64位下的性能。

  于是选择最新的VC系列编译器——Visual C++ 2010,它是2010年发售的,支持x64平台。

一、代码改进

1.1 通用字符处理——tchar.h

  传统的Windows程序一般使用ANSI+DBCS字符集。而从Windows NT开始,Windows内核采用Unicode字符集。但那时基于ANSI+DBCS的Win9X系统还很流行,所以VC6默认使用ANSI+DBCS字符集。

  虽然VC6中也有用于通用字符处理的“tchar.h”。但考虑到传统的C语言教学,一般很少用到它。

  如今WinXP替代Win9X已经有很多年了,甚至都快被Win7取代了,ANSI+DBCS字符集已经退出历史舞台。于是VC2010默认使用Unicode字符集。我们应使用“tchar.h”做通用字符处理。使用要点有——

1.字符类型。用“_TCHAR”替代“char”。
2.字符串常量。用“_T”这个宏来定义字符串常量。如“_T("\n")”。
3.字符串函数。相对于传统的C语言标准函数,tchar函数的特点是函数名前面多了“_t”。如“_tprintf(_T("\n"));”
4.程序入口。传统C语言程序的入口是“main”函数,而现在是“_tmain”函数。如“int _tmain(int argc, _TCHAR* argv[])”。

1.2 检测64位环境

  因考虑到程序会在64位环境下运行,所以需要检测64位环境。检测方法——

VC 64位程序开发心的——获得程序位数和操作系统位数

二、全部代码

  全部代码——

// 用位掩码做饱和处理.用求负生成掩码 #define LIMITSU_FAST(n, bits) ( (n) & -((n) >= 0) | -((n) >= (1<<(bits))) ) #define LIMITSU_SAFE(n, bits) ( (LIMITSU_FAST(n, bits)) & ((1<<(bits)) - 1) ) #define LIMITSU_BYTE(n) ((BYTE)(LIMITSU_FAST(n, 8))) // 用位掩码做饱和处理.用带符号右移生成掩码 #define LIMITSW_FAST(n, bits) ( ( (n) | ((signed short)((1<<(bits)) - 1 - (n)) >> 15) ) & ~((signed short)(n) >> 15) ) #define LIMITSW_SAFE(n, bits) ( (LIMITSW_FAST(n, bits)) & ((1<<(bits)) - 1) ) #define LIMITSW_BYTE(n) ((BYTE)(LIMITSW_FAST(n, 8))) // 数据规模 #define DATASIZE    16384    // 128KB / (sizeof(signed short) * 4) // 缓冲区 signed short    bufS[DATASIZE*4];    // 源缓冲区。64位的颜色(4通道,每通道16位) BYTE    bufD[DATASIZE*4];    // 目标缓冲区。32位的颜色(4通道,每通道8位) // 测试时的函数类型 typedef void (*TESTPROC)(BYTE* pbufD, const signed short* pbufS, int cnt); // 用if分支做饱和处理 void f0_if(BYTE* pbufD, const signed short* pbufS, int cnt) {
const signed short* pS = pbufS; BYTE* pD = pbufD; int i; for(i=0; i
255) ? 255 : (BYTE)pS[0] ); pD[1] = (pS[1]<0) ? 0 : ( (pS[1]>255) ? 255 : (BYTE)pS[1] ); pD[2] = (pS[2]<0) ? 0 : ( (pS[2]>255) ? 255 : (BYTE)pS[2] ); pD[3] = (pS[3]<0) ? 0 : ( (pS[3]>255) ? 255 : (BYTE)pS[3] ); // next pS += 4; pD += 4; } } // 用min、max饱和处理 void f1_min(BYTE* pbufD, const signed short* pbufS, int cnt) {
const signed short* pS = pbufS; BYTE* pD = pbufD; int i; for(i=0; i
")); _getch(); } _tprintf(_T("\n")); // 进行测试 runTest(_T("f0_if"), f0_if); runTest(_T("f1_min"), f1_min); runTest(_T("f2_neg"), f2_neg); runTest(_T("f3_sar"), f3_sar); // 结束前提示 if (argc<=1) {
_tprintf(_T("
")); _getch(); } _tprintf(_T("\n")); return 0; }

三、配置与编译

3.1 输出汇编代码

  配置方法如下——

1.点击菜单栏的 项目->属性,打开项目的属性页。
2.在左边的功能树中选择 配置属性->C/C++->输出文件。
3.在右边的“汇编程序输出”中选择“带源代码的程序集”。

3.2 配置winmm.lib库

  配置方法如下——

1.点击菜单栏的 项目->属性,打开项目的属性页。
2.在左边的功能树中选择 配置属性->链接器->输入。
3.在右边的“附加依赖项”中添加“Winmm.lib”。

3.3 配置x64平台

  点击菜单栏的 生成->配置管理器,打开“配置管理器”对话框,新建平台“x64”。

  具体细节可参考MSDN——

如何:针对 64 位平台配置 Visual C++ 项目

3.4 编译生成

  点击菜单栏的 生成->批生成。生成Release版。

四、测试结果

  运行“Release\noifVC2010.exe”,在32位winXP上的测试结果——

== noif:VC2010(32) on 32bit ==
f0_if[1]: 1793 f0_if[2]: 1812 f0_if[3]: 1733 f1_min[1]: 2112 f1_min[2]: 2111 f1_min[3]: 2132 f2_neg[1]: 511 f2_neg[2]: 519 f2_neg[3]: 512 f3_sar[1]: 442 f3_sar[2]: 436 f3_sar[3]: 437

 

  运行“Release\noifVC2010.exe”,在64位win7上的测试结果——

== noif:VC2010(32) on 64bit ==
f0_if[1]: 1731 f0_if[2]: 1716 f0_if[3]: 1685 f1_min[1]: 2106 f1_min[2]: 2106 f1_min[3]: 2090 f2_neg[1]: 500 f2_neg[2]: 514 f2_neg[3]: 515 f3_sar[1]: 437 f3_sar[2]: 421 f3_sar[3]: 437

 

  运行“x64\Release\noifVC2010.exe”,在64位win7上的测试结果——

== noif:VC2010(64) on 64bit ==
f0_if[1]: 1638 f0_if[2]: 1623 f0_if[3]: 1622 f1_min[1]: 1997 f1_min[2]: 1997 f1_min[3]: 2012 f2_neg[1]: 421 f2_neg[2]: 437 f2_neg[3]: 421 f3_sar[1]: 328 f3_sar[2]: 327 f3_sar[3]: 328

 

  硬件环境——

CPU:Intel Core i3-2310M, 2100 MHz
内存:DDR3-1066

 

源码下载——

(建议阅读编译器生成的汇编代码,位于“Release\noifVC2010.asm”、“x64\Release\noifVC2010\noifVC2010.asm”)

转载地址:http://zfwsl.baihongyu.com/

你可能感兴趣的文章
ios学习笔记(二)第一个应用程序--Hello World
查看>>
Maven学习总结(四)——Maven核心概念——转载
查看>>
怎么用CIFilter给图片加上各种各样的滤镜_2
查看>>
android:关于主工程和library project
查看>>
CodeForces 2A Winner
查看>>
Window环境配置Mongodb
查看>>
制作和unity调用动态链接库dll文件
查看>>
exsi6.0远程修改密码
查看>>
Header和Cookie相关内容
查看>>
20个可能你不知道Linux网路工具
查看>>
Android 关于listView 显示不全的问题
查看>>
构造函数创建私有变量(防继承)
查看>>
scrum 开发方式学习笔记
查看>>
Terraform使用案例
查看>>
Mac下brew方式安装mysql
查看>>
开源的任务队列服务HTQ
查看>>
通过微信小程序看前端
查看>>
[LeetCode] Rotate Function
查看>>
iOS - 更轻量级的 AppDelegate - 面向服务设计
查看>>
什么样的爬虫才是好爬虫:Robots协议探究
查看>>