표준 라이브러리.. 따라잡기...

philossh의 이미지

int asmstrlen(const char* ch)
{
	__asm
	{
		mov edi, dword ptr [ebp+8];
		xor al, al;
		mov ecx, -1;
      repne scasb;
		xor eax, eax;
		mov eax, -2;
		sub eax, ecx;
	}
}

표준라이브러리의 strlen() 함수를 따라잡아보려고..
거의 모르는 어셈까지 써가며 해봤는데..
결과는 처참하네요..
(똑바로된 어셈을 작성할 능력이 없어서 그런지는 몰라도.. :oops:)

for루프를 약 1000만번 돌리니..
표준 : 약 250 ms
허접한어셈: 약 850 ms
아래처럼하면.. 약 2300 ms 정도..

int mystrlen(const char* ch)
{
	int i=0;
	while (*ch++) i++;
	return i;
}

흠.. TC++PL 6장연습문제에서 한번 만들어봐라고 해서 만들어 봤다가..
흠.. 역시나.. 미숙한 나로서는..
책의 의도대로 표준라이브러리에 대한 의심을 버리는게.. 흐흐.. :roll:

eungkyu의 이미지

다음은 glibc 2.3.5의 코드입니다.

size_t
strlen (const char *str)
{
  int cnt;

  asm("cld\n"                   /* Search forward.  */
      /* Some old versions of gas need `repne' instead of `repnz'.  */
      "repnz\n"                 /* Look for a zero byte.  */
      "scasb" /* %0, %1, %3 */ :
      "=c" (cnt) : "D" (str), "0" (-1), "a" (0));

  return -2 - cnt;
}

전 어셈을 잘 몰라서 정확히 해석할 순 없지만 i386에 서치하는 인스트럭션이 있는가봅니다

그것보다, strstr의 glibc 코드에는 다음과 같은 코멘트가 달려있죠.

/*
 * My personal strstr() implementation that beats most other algorithms.
 * Until someone tells me otherwise, I assume that this is the
 * fastest implementation of strstr() in C.
 * I deliberately chose not to comment it.  You should have at least
 * as much fun trying to understand it, as I had to write it :-).
 *
 * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */
mmojz의 이미지

제가 간단히 아는 ㅇ명령어로만 해봤는데 결과가 아주 비참하군요!!

셀러론 1Ghz 입니다.

__declspec(naked) int mmojz_strlen(const char* s)
{
	__asm
	{
		push ebp
		mov ebp, esp
	}
	__asm
	{
		push ecx
		push esi
		mov ecx, -1
		mov esi, dword ptr[ebp+8];
		cld
l:
		lodsb
		inc ecx
		cmp al, 0
		jne l
		mov eax, ecx
		pop esi
		pop ecx
	}
	__asm
	{
		pop ebp
		ret
	}
}

int mmojz2_strlen(const char* ch) 
{ 
	int i=0; 
	while (*ch++) i++; 
	return i; 
} 

int main()
{	
	unsigned int t;


	t = timeGetTime();
	for(volatile unsigned int i=0; i<10000000; i++)
	{
		strlen("345349534583495834958589358938595");
	}
	printf("라이브러리 : %d\n", timeGetTime()-t);

	t = timeGetTime();
	for(volatile unsigned int i=0; i<10000000; i++)
	{
		mmojz_strlen("345349534583495834958589358938595");
	}
	printf("허접 어셈 : %d\n", timeGetTime()-t);

	t = timeGetTime();
	for(volatile unsigned int i=0; i<10000000; i++)
	{
		mmojz2_strlen("345349534583495834958589358938595");
	}
	printf("C언어 : %d\n", timeGetTime()-t);
	return 0;
}

debug 버전에서는
라이브러리 : 1065
허접 어셈 : 2658
C언어 : 6016

Release 버전에서는
라이브러리 : 89
허접 어셈 : 2625
C언어 : 941

비참...


philossh wrote:
int asmstrlen(const char* ch)
{
	__asm
	{
		mov edi, dword ptr [ebp+8];
		xor al, al;
		mov ecx, -1;
      repne scasb;
		xor eax, eax;
		mov eax, -2;
		sub eax, ecx;
	}
}

은 Release 버전에서는 작동하지 않습니다. (.NET 2003 입니다.)
lifthrasiir의 이미지

philossh 님께서 올리신 코드는 eungkyu 님께서 올리신 glibc 코드와 본질적으로 같은 의미 같습니다. 그런데도 속도 차이가 그렇게 난다면, 마이크로소프트에서 제공하는 구현이 무진장 효과적이거나-_- 아니면 외부적인 요인이 작용할 가능성이 높을 것 같네요. (호출 규약을 naked로 하는 것도 한 방법입니다만 저 정도로 차이가 난다면 좀...)

eungkyu wrote:
전 어셈을 잘 몰라서 정확히 해석할 순 없지만 i386에 서치하는 인스트럭션이 있는가봅니다

repnz scasb(또는 repne scasb)의 역할이 바로 그것입니다. 일반적으로 많은 메모리를 한꺼번에 초기화하거나, 특정한 값을 찾을 때는 rep 접두사를 쓰는 명령이 가장 빠를 것입니다. (한 명령으로 다 해 먹으니까) mmojz 님의 코드가 느릴 수 밖에 없는 것도 같은 이유죠.

...그냥 표준 라이브러리 그대로 쓰는 게 속 편하죠 암암 -_-;

- 토끼군

kane의 이미지

int foo_strlen(const char* c)
{
  const char* p = c;
  while(*p++);
  return p-1-c;
}

조금은 나을꺼라고 생각하고 작성했는데 더 느리군요. :sad:
이 포스트의 의도대로 저에 대한 믿음을 버리는게.. 흐흐.. ㅠㅜ

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.