2009-11-21 5 views
7

대표 문자 strlen()이 (가) \0이 될 때까지 첫 번째 문자에서부터 이동합니다. 각 문자를 통과해야합니다. 알고리즘의 의미에서 O (N).빠른 strlen?

입력이 모호하게 정의 된 경우 더 빠르게 수행 할 수 있습니까? Like : 길이가 50보다 작거나 길이가 약 200 자입니다.

내가 조회 블록을 생각했지만 모든 최적화를 얻지 못했습니다.

+8

물론 : 여기

는 새로운 지침에 대한 몇 가지 흥미로운 생각이다. 'return 4;'. 번개가 빠른 것을 보장합니다! 번호는 공정한 주사위 굴림에 의해 결정되었습니다. – Geo

+1

@Geo [Cute] (https://xkcd.com/221/). 그러나 대다수 입력에 대해 'strlen'을 구현하지 않습니다. – imallett

답변

17

사실 strlenglibc's implementation는 벡터화 방법의 흥미로운 예이다.벡터 명령어를 사용하지 않지만 버퍼의 32 또는 64 비트 워드에 대한 일반 명령어 만 사용하는 방법을 찾습니다.

+0

참으로 영리한! –

+0

한편, 최소한 x86/x86_64와 gcc에서는 컴파일러의 내장을 얻을 수 있습니다. – LnxPrgr3

+0

예, 사용하는 버전이 귀하의 버전인지 확인하려면 다른 이름을 지정해야합니다. 이 작업을 수행하려는 경우 버전을 전달할 모든 문자열이 단어 정렬 (가능한 경우)되도록하고 초기 char-by-char 루프를 완전히 제거 할 수도 있습니다. –

22

확실히. 문자열에 쓰는 동안 길이를 추적하십시오.

+9

+1 : 만세 파스칼! –

+1

+1 : Hooray Fortran (선언 후에 어떤 식 으로든 변경할 수 없음) –

+0

이 기술을 사용하여 strcat에 큰 개선을했습니다. – Mandrake

6

짧은 대답 : 아니오.

대답 : 베어 본 C 문자열의 문자열 길이를 확인하는 더 빠른 방법이 있다면 일반적으로 C 문자열 라이브러리로 사용되는 것이 이미 통합되지 않았을 것이라고 생각하십니까?

문자열에 대한 추가 지식 없이는 각 문자를 확인해야합니다. 추가 정보를 유지하려면 struct의 필드 (실제 문자 배열/문자열 포인터)에 길이를 저장하는 struct을 만들 수 있습니다.이 경우 길이를 만들 수 있습니다 조회 상수 시간이지만 문자열을 수정할 때마다 해당 필드를 업데이트해야합니다.

+0

우리는 파스칼 문자열을 다시 가질 수 있습니다. :) – wadesworld

+1

그러나 우리는 아마도 버퍼 오버 플로우가 더 적었을 것입니다 (만약 그들이 언어에 내장되어 있거나 일관되게 사용 되었다면) - 그것은 좋은 것일 것입니다! –

9

문자열의 최소 길이가 알려진 경우 분명히 그 위치에서 검색을 시작할 수 있습니다. 그 너머

, 당신이 할 수있는 일이 정말이 아니다; 똑똑한 것을 시도하고 \0 바이트를 찾으려고한다면 문자열의 시작과 그 지점 사이의 모든 바이트를 확인하여 이전 \0이 없는지 확인해야합니다. strlen 최적화 할 수없는 것은 아니다

. 그것은 파이프 라인 될 수 있으며 각 비교시 워드 크기 또는 벡터 청크를 처리하도록 만들 수 있습니다. 대부분의 아키텍처에서 이러한 접근 방식과 다른 접근 방식을 조합하면 순진한 바이트 비교 루프에 비해 실질적인 일정 속도가 향상됩니다. 물론 대부분의 성숙한 플랫폼에서 시스템 strlen은 이미 이러한 기술을 사용하여 구현됩니다.

3

벡터화를 사용해 볼 수 있습니다. 컴파일러에서 수행 할 수 있는지 확실하지 않지만 수동으로 수행했습니다 (내장 함수 사용). 그러나 그것은 긴 문자열에 대해서만 당신을 도울 수 있습니다.

stl 문자열을 사용하면 더 안전하며 std :: string 클래스의 길이가 포함됩니다. , 당신은 길이가 200 자입니다 알고 있다고 생각, 이제

size_t 
strlen(const char *str) 
{ 
     const char *s; 

     for (s = str; *s; ++s) 
       ; 
     return (s - str); 
} 

:

+0

벡터화가 어떻게 도움이됩니까? 버퍼가 말하자면 4KB라고해도 첫 번째 null 다음에 문자열의 내용에 대한 보장이 없으므로 벡터화가 1KB 경계에서 4 가지 작업 (스레드?)을 시작하면 3 가지로 시작하는 0이 아닌 오프셋이 나타납니다. 결과가 반환 된 4 개의 값 중 최소값이어야한다고 가정합니다. 0이 아닌 오프셋 스레드는 반환 된 길이에 시작 위치를 추가해야합니다. –

+0

Elalfer는 연속 된 각 바이트를 벡터 전체에 할당 한 다음 벡터의 길이에 대한 문자열 스캔을 스크롤하도록 제안한다고 생각합니다. 벡터 기반 아키텍처가 있다고 가정하면 확실히 작동합니다. –

+2

@Jonathan 벡터화가 스레드를 사용하지 않습니다! 벡터화는 SIMD 프로그래밍 모델을 사용하여 연속적인 바이트를 동시에 0으로 확인하는 것을 의미합니다. http://en.wikipedia.org/wiki/SIMD 벡터 정렬을 사용하면 항상 한 페이지에 맞출 수 있습니다. 이 구현은 일반적으로 버퍼를 오버플로하지만 MMU가 캐치하지 않습니다. 우리는 내가 작업하는 분석기에서 이러한 양성 버퍼 오버 플로우를 발견합니다. 특별한 벡터 명령어없이 인상적인 C 코드를 구현하려면 http://tsunanet.net/~tsuna/strlen.c.html을 참조하십시오. –

4

잭의 '\ 0'종료를 찾아

strlen 작품, 여기에 오픈 BSD에서 찍은 구현입니다 너는 말했다. 200에서 시작하여 '\ 0'에 대해 위아래로 반복한다고 가정 해보십시오. 당신은 204에서 하나를 발견했습니다, 그것은 무엇을 의미합니까? 그 문자열은 204 문자 길이입니까? 아니! 그 전에 다른 '\ 0'으로 끝날 수 있었고 당신이했던 모든 일은 한계를 벗어났습니다.

+0

답변 해 주셔서 감사합니다. 길이가 막연하게 예측되어 문자 200 이후에 끝나지 않을 수도 있습니다. 또한 200 번째 문자 뒤에 읽는다면 잘못된 문자열을 읽을 수 있습니다 (문자열이 100 자 정도 끝나면 ...) – Jack

+0

링크도 말합니다 동일 : http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/string/strlen.c?annotate=1.7 – Jack

3

코어 i7 프로세서를 구입하십시오.

코어 i7에는 SSE 4.2 명령어 세트가 제공됩니다. 인텔은 strlen 및 관련 검색 작업의 속도를 높이기 위해 추가로 4 가지 벡터 지침을 추가했습니다.

http://smallcode.weblogs.us/oldblog/2007/11/

+0

답변 해 주셔서 감사합니다. George Verghese가 말했듯이, 하드웨어 부스트가 항상 도움이됩니다. :) – Jack