内存初始化选用CPU指令疑问

yaos 2008-04-03 03:45:41
做内存清零函数的优化
两个函数
分别用两条指令
一个movdqa, 一个movntdq
数据尺寸(双字串长)小时第一个好,数据尺寸大时第二个好
在尺寸为135000-136000范围开始第二个函数表现开始好于一
(纳闷的是不是512k/4=131072)
二级缓存是512k 一级缓存是8k
请问如何切分分界点

#include <stdio.h>
#include <windows.h>

#define TestCount 10000

DWORD TestD[655360];

//应该总假定是双字串
void AsmMemZero0(unsigned long * p, unsigned long t)
{
__asm
{
xor eax, eax
cld
mov edi, dword ptr [p]
mov edx, t
test edx, 0xFFFFFFFF
je exit0
test edi, 15 //是否16字节对齐
je AsmZero1
mov ecx, edi
and ecx, 0xFFFFFFF0
add ecx, 16
sub ecx, edi //得到需要双字复制部分,要和edx比较谁大
shr ecx, 2 //转换为双字长度
mov ebx, ecx
cmp ecx, edx
ja AsmZero2 //不足,转尾处理
AsmZero01:
mov dword ptr [edi], eax
add edi, 4
sub ecx, 1
jne AsmZero01
sub edx, ebx
je exit0 //是否刚好
AsmZero1: //16字节对齐
mov ecx, edx
shr ecx, 2
je AsmZero2 //是否不足16字节
pxor xmm0, xmm0
AsmZero11:
movdqa [edi], xmm0
add edi, 16
sub ecx, 1
jne AsmZero11
AsmZero2:
mov ecx, edx
and ecx, 15
je exit0
AsmZero3:
mov dword ptr [edi], eax
add edi, 4
sub ecx, 1
jne AsmZero3
exit0:
}
}

//应该总假定是双字串
void AsmMemZero1(unsigned long * p, unsigned long t)
{
__asm
{
xor eax, eax
cld
mov edi, dword ptr [p]
mov edx, t
test edx, 0xFFFFFFFF
je exit0
test edi, 15 //是否16字节对齐
je AsmZero1
mov ecx, edi
and ecx, 0xFFFFFFF0
add ecx, 16
sub ecx, edi //得到需要双字复制部分,要和edx比较谁大
shr ecx, 2 //转换为双字长度
mov ebx, ecx
cmp ecx, edx
ja AsmZero2 //不足,转尾处理
AsmZero01:
mov dword ptr [edi], eax
add edi, 4
sub ecx, 1
jne AsmZero01
sub edx, ebx
je exit0 //是否刚好
AsmZero1: //16字节对齐
mov ecx, edx
pxor xmm0, xmm0
shr ecx, 2
je AsmZero2 //是否不足16字节
AsmZero11:
movntdq [edi], xmm0
add edi, 16
sub ecx, 1
jne AsmZero11
AsmZero2:
mov ecx, edx
and ecx, 15
je exit0
AsmZero3:
mov dword ptr [edi], eax
add edi, 4
sub ecx, 1
jne AsmZero3
exit0:
sfence
}
}

//应该总假定是双字串
void AsmMemZeroALU(unsigned long * p, unsigned long t)
{
__asm
{
xor eax, eax
cld
mov edi, dword ptr [p]
mov ecx, t
test ecx, 0xFFFFFFFF
je exit0
rep stosd
exit0:
}
}

int main(void)
{
UINT64 s_u64Frequency = 1;
UINT64 s_u64Start, s_u64End;
unsigned long i, TestSize;

printf("Input Test Size: ");
scanf("%ld", &TestSize);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);

QueryPerformanceFrequency((LARGE_INTEGER *)&s_u64Frequency );
QueryPerformanceCounter((LARGE_INTEGER *)&s_u64Start );
for (i = 0; i < TestCount; i ++)
AsmMemZero0(&TestD[0], TestSize);
QueryPerformanceCounter((LARGE_INTEGER *)&s_u64End );

printf( "func 0 Elapsed time: %.3f ms\n",
(double)(( s_u64End - s_u64Start ) * 1000.0 / (double)s_u64Frequency ));

QueryPerformanceFrequency((LARGE_INTEGER *)&s_u64Frequency );
QueryPerformanceCounter((LARGE_INTEGER *)&s_u64Start );
for (i = 0; i < TestCount; i ++)
AsmMemZero1(&TestD[0], TestSize);
QueryPerformanceCounter((LARGE_INTEGER *)&s_u64End );

printf( "func 1 Elapsed time: %.3f ms\n",
(double)(( s_u64End - s_u64Start ) * 1000.0 / (double)s_u64Frequency ));

return 0;
}
...全文
168 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
knowledge_Is_Life 2008-05-01
  • 打赏
  • 举报
回复
接分是王道!
我啃 2008-04-12
  • 打赏
  • 举报
回复
emath上已经贴了相关新文
cnzdgs 2008-04-12
  • 打赏
  • 举报
回复
cache没玩过,不敢乱说。
yaos 2008-04-12
  • 打赏
  • 举报
回复
就没人能帮助么?

如何通过CPUID找到L2cache容量?
guoxyj 2008-04-04
  • 打赏
  • 举报
回复
gz
yaos 2008-04-03
  • 打赏
  • 举报
回复
我想找到一个明确的转折点
因为
在数据长度很小时movntdq很差
在数据长度很大时movdqa很差
数据已考虑16字节对齐

21,459

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧