1. 知识准备
1)计算函数的运行时间
要想获取一个函数的运行时间,可直接在该函数的运行前后,添加一个计时函数,但可能会存在一个问题,大多数函数运行时间较短,因此需要一个精度非常大的函数,经查找,最终选用windows.h下的函数,通过时钟来计算时间差。
先通过QueryPerformanceFrequency()获取时钟周期数;
再通过QueryPerformanceCounter()获取时钟计数;
计算函数运行所用的总时钟数,再除以时钟周期数,即可计算出相应时间。单位为微妙
2)通过指针复制字节
定义指针时,需要指定指针类型,如char、int ,如int * a,变量a 表示4个字节,char * b,变量b表示1个字节。
int *a;
int *b;
*a=*b;
这个操作,是4个字节的
如果把int 改为char,则这个操作是一个字节的
2.提出问题
利用这个特性,产生如下想法:
在达夫设备的基础上,对于同一个char型文件,通过指针赋值 的方式,把每次复制1个字节变成每次复制4个字节,是否会把速度提得更快呢?
当然,这种方式可能会产生以下问题:
该char型文件的大小,若不是4的倍数,剩下的“尾巴”该如何处理?
3.解决方式
#include <stdio.h>
#include <time.h>
#include <windows.h>
#define N 1000
double duration;
void duffC_device(char *from, char *to, int count);
void duffI_device(char *from, char *to, int count);
LARGE_INTEGER m_nFreq;
LARGE_INTEGER m_nBeginTime;
LARGE_INTEGER m_nEndTime;
int main(int argc, char** argv) {
char str[N]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','0','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p',
'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p'};
char cstr[N]={0};
QueryPerformanceFrequency(&m_nFreq); // 获取时钟周期
QueryPerformanceCounter(&m_nBeginTime); // 获取时钟计数
duffC_device(str,cstr,N);
QueryPerformanceCounter(&m_nEndTime);
// for(int i=0;i<N;i++) //将其打印输出,测试内容和数量是否复制正确
// printf("%c ",cstr[i]);
printf("\nticks 1= %lf\n", (double)(m_nEndTime.QuadPart-m_nBeginTime.QuadPart)*1000/m_nFreq.QuadPart);
QueryPerformanceCounter(&m_nBeginTime); // 获取时钟计数
duffI_device(str,cstr,N);
QueryPerformanceCounter(&m_nEndTime);
//for(int i=0;i<N;i++)
// printf("%c ",cstr[i]);
printf("\nticks 4= %lf\n", (double)(m_nEndTime.QuadPart-m_nBeginTime.QuadPart)*1000/m_nFreq.QuadPart);
// system("pause");
return 0;
}
void duffC_device(char *from, char *to, int count) //每次读取1个字节
{
int n = (count + 7) / 8;
switch(count % 8) {
case 0: do { *to++ = *from++;
case 7: *to++ = *from++;
case 6: *to++ = *from++;
case 5: *to++ = *from++;
case 4: *to++ = *from++;
case 3: *to++ = *from++;
case 2: *to++ = *from++;
case 1: *to++ = *from++;
} while(--n > 0);
}
}
void duffI_device(char *from, char *to, int count)
{
int rem=count%4; // 处理余4的“尾巴部分”(这部分不够一个int字节,否则越界,需提前处理)
switch(rem){
case 3: *to++ = *from++;
case 2: *to++ = *from++;
case 1: *to++ = *from++;
}
int *dFrom=(int *)(from); //用一个int型指针,指向4个char字节
int *dTo=(int *)(to);
count=count/4; //char 用int指针表示后,总数量变为count/4(记得除4哦,否则每次都会多读12个字节)
int n = (count + 7) / 8;
switch(count % 8) {
case 0: do { *dTo++ = *dFrom++;
case 7: *dTo++ = *dFrom++;
case 6: *dTo++ = *dFrom++;
case 5: *dTo++ = *dFrom++;
case 4: *dTo++ = *dFrom++;
case 3: *dTo++ = *dFrom++;
case 2: *dTo++ = *dFrom++;
case 1: *dTo++ = *dFrom++;
} while(--n > 0);
}
}
4.测试结果
经测试,随着复制数量的增大,两者复制速度差也越来越大
这样的处理还是有一些效果的,尤其是在调试的时候,两种方法所循环次数以及赋值次数的比较,后者真的是很爽了!
哈哈,不足之处还请各位佬大多多指教!٩(๑>◡<๑)۶