优化不是你想像-3:三种不同的方式

 
让我们来看看实际的例子,在这个例子中,我们尝试使用两种不同的方法来优化memcpy函数,并对16K,128K,256K,512K,1M,2M,4M,16M,32M,64M的数据进行拷贝操作(由于误操作,32K, 64K的被意外删除了,由于懒惰,没有重新统计),同时还使用两种不同尺寸的预取块,然后对其结果进行比较。
所有数据都在16字节边界上对齐。
 
作为参照的使用指针的for 循环操作:
void test_for(char* src, char* dst, int size)
{
    for ( int a = 0; a < size / sizeof(int); a++)
    {
        *(int *)dst = *(int *)src; // 进行整数赋值
        dst += 4; // 下一次迭代地址
        src += 4;
    }
}
 
使用汇编进行预取操作
// 页面大小:4096
#define PAGE_SIZE    4096
// 预取字节,当为缓存线长度时最佳,PIII为32,P4及Xeon为128,作为比较,在测试中也使用了不同值
#define PREFETCH_SIZE 128
__forceinline void __fastcall __prefetchnta(char* x)
{
    __asm
    {
        mov eax, [x]
        _emit 0xF
        _emit 0x18
        _emit 0x0
    }
}
流式拷贝函数
__forceinline void __fastcall __stream_cpy(char* dst, char* src)
{
    __asm
    {
        mov eax, [src]
        mov edx, [dst]
        _emit 0xF
        _emit 0x28
        _emit 0
 
        _emit 0xF
        _emit 0x2B
        _emit 0x2
    }
}
使用预取方式优化的的拷贝函数
int test_perfetch(char* src, char* dst, int size)
{
    int a, b, temp;
   
    for ( a = 0; a < size; a += PAGE_SIZE )
    {
        temp = *(int *)(src + a + PAGE_SIZE);
 
        for(b = a; b < a + PAGE_SIZE; b+= PREFETCH_SIZE) //预取到缓存
            __prefetchnta(src + b);
       
        for(b = a; b < a + PAGE_SIZE; b += 16 * 8) // 拷贝,每个迭代128字节
        {
            __stream_cpy(dst + b + 16 * 0, src + b + 16 * 0);
            __stream_cpy(dst + b + 16 * 1, src + b + 16 * 1);
            __stream_cpy(dst + b + 16 * 2, src + b + 16 * 2);
            __stream_cpy(dst + b + 16 * 3, src + b + 16 * 3);
            __stream_cpy(dst + b + 16 * 4, src + b + 16 * 4);
            __stream_cpy(dst + b + 16 * 5, src + b + 16 * 5);
            __stream_cpy(dst + b + 16 * 6, src + b + 16 * 6);
            __stream_cpy(dst + b + 16 * 7, src + b + 16 * 7);
        }
    }
 
    return temp;
}
 
使用QueryPerformanceFrequency来计算花费的时间
//申明时间度量变量
#define DECL_PERF()     __int64 m_CounterFreq, m_CounterStart, m_CounterEnd;
//初始化时间变量
#define INIT_PERF()     QueryPerformanceFrequency((LARGE_INTEGER *)&m_CounterFreq);
//记录操作开始时间
#define BEGIN_PERF()    QueryPerformanceCounter((LARGE_INTEGER *)&m_CounterStart);
//记录结束时间
#define END_PERF()      QueryPerformanceCounter((LARGE_INTEGER *)&m_CounterEnd);
//计算操作耗费的时间
#define GET_PERF()      ((m_CounterEnd - m_CounterStart) / (FLOAT)m_CounterFreq)
 

运行完成后,将统计数据导入到EXCEL中,制成图表,进行比较。 

寒一个,居然无法上传!!!

若有意索取源代码和原始文档,请信至:[email protected]

你可能感兴趣的:(优化,Stream,汇编,Excel,Integer,DST)