영어사전에서 영어단어 검색 속도
어느 신문사의 기사글에서 옥스포드 영어사전에 등재되어 있는 영어단어 수는 약 30만(3 x 10의5승)개 라고 하는군요.
그런데 일상생활에서 통용되는 단어(방언, 신조어 등..)들까지 합하면 약 100만(10의6승)개의
영어단어가 있다고 볼 수 있습니다.
저의 관심사는 약 100만개에 해당하는 영어단어를 컴퓨터 메모리에 영어사전 형태로 구축했을때,
하나의 단어를 검색하는데 얼마의 시간이 소요 되는가? 입니다.
요즘 컴퓨터의 CPU 처리속도는 보통 수 GHz 입니다.
즉, CPU 내부에서 1 클럭(디지털 신호가 On/Off로 변화되는 클럭)은 약 10의-9승초(0.001마이크로초) 걸린다는 것입니다.
CPU 제조사 마다 조금씩 다르겠지만, 1개의 기계명령이 100클럭으로 설계되었다면,
하나의 명령을 수행하는데 0.1 마이크로초가 소요됩니다.
여기서, 하나의 문자를 비교하는데 10개의 기계명령이 필요하다면,
하나의 문자 비교에 1마이크로(10의-6승)초가 소요됩니다.
영어단어가 평균 10개의 문자로 구성되었다고 보면,
하나의 영어단어를 비교하는데 약 10마이크로(10의-5승)초가 걸린다고 계산할 수 있습니다.
그렇다면, 컴퓨터 메모리에 100만개의 영어단어가 저장되어 있다고 할때,
하나의 영어단어를 검색하는데 소요되는 시간은 아래와 같이 쉽게 산출해 볼 수 있습니다.
(1) 최선의 경우: 영어단어 1번 비교 --> 10마이크로(10의-5승)초 (2) 최악의 경우: 영어단어 100만번 비교 --> (10의6승) x (10의-5승) --> 10초 (3) 평균: 최악의 경우 / 2 --> 5초
1GHz의 CPU 클럭속도를 가지는 컴퓨터에서 1초는 실제로 엄청나게 긴 시간입니다.
위의 결과는 100만개의 영어단어를 컴퓨터 메모리에 배열형태로 쭉 나열했을때의 자료구조를 가정한 결과입니다.
그렇다면, 영어단어 검색을 가장 빠르고 효율적으로 할 수 있는 자료구조와 알고리즘은 어떤 것들이 있을까요?
from 알지비(rgbi3307(at)nate.com) on the www.kernel.bz
이런 경우 순차 검색은 잘 안씁니다. 정렬된 경우의
이런 경우 순차 검색은 잘 안씁니다.
정렬된 경우의 검색 알고리즘은 많고요. (이진 검색 등)
단어 색인 검색에는 트라이 같은 구조를 많이 쓰는 것으로 알고 있습니다.
-----
오늘 나의 취미는 끝없는, 끝없는 인내다. 1973 法頂
저도 알고 싶던데요.
무궁화'를 검색하면
무 - 지 - 개
---- 궁 - 무 - 진
무 - 궁 - 화
단어를 해시로 만들어서 하나씩 나눠서 찾는게 제일 빠를거 같은데요.
이건 단점이 중간 값만 찾고 싶은데 중간부터는 찾지를 못하겠드라구요.
궁화. 이렇게 검색을 못해요;;;;
그래서. 궁 - 화'까지 디비에 넣으면 용량이 무식해지고... 효율도 없고... 하튼 잘아시는분 말씀 점 들어봤으면 좋겠네요.
----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
단어가 가진 문자의 수를 미리 인덱스 시켜놓고,
단어가 가진 문자의 수를 미리 인덱스 시켜놓고, 찾으려는 단어의 문자 수와 같은 경우에만 비교하기 시작하는건 어떨까요?
피할 수 있을때 즐겨라! http://melotopia.net/b
인덱스+이진검색
찾으려는 값을 통해서 대충 인덱스로 잡은다음 최소한의 규모로 이진 검색을 하면될꺼 같은데요?
각각의 단어 대표값으로 묶어놓으면 되겠죠.
(윗분대로라면 무 라는 공통점으로 묶이겠군요.) 그다음 찾은 인덱스의 묶음에서 이진 검색을 하면 될꺼 같습니다.
중간단어를 입력해서 찾는 방법도 동일하게 인덱스로 묶었다면 사용할수 있을꺼 같습니다.
인덱스의 탐색도 순차가 아닌 이진 검색을 한다면 더 효율적이 될꺼 같습니다.
저의 처음 발제글은 100만개의 단어를 순차검색
저의 처음 발제글은 100만개의 단어를 순차검색 했을때,
(1) 최선의 경우: 영어단어 1번 비교 --> 10마이크로(10의-5승)초
(2) 최악의 경우: 영어단어 100만번 비교 --> (10의6승) x (10의-5승) --> 10초
(3) 평균: 최악의 경우 / 2 --> 5초
이러한 시간이 걸린다는 것이었습니다.
앞에서 말씀하신 것처럼, 이진검색을 많이 사용하는데,
이진검색은 기본적으로 검색대상이 정렬되어 있어야 하며,
100만개의 단어를 정렬하는 시간이 필요하다는 단점이 있습니다.
그래서, 100만개의 단어가 처음에 입력될때부터 정렬되는 순서대로 메모리에
저장시키는 방식으로 이진탐색트리(Binary Search Tree)가 있습니다.
BST 자료구조를 사용하면 정렬시간이 필요없게 됩니다.
그런데, BST의 단점은 트리의 깊이(height)가 깊어질 수 있습니다.
이 단점을 보안한 것이 BTree입니다. BST는 order가 2인 BTree라고 볼 수 있습니다.
order가 10인 BTree에 100만개의 단어를 저장하면,
BTree의 깊이(height)는 log(10의6승) --> 6이 됩니다.
따라서, BTree에서는 단어를 최소 6번, 최대 6번 x order --> 60번만 비교하면 되고,
시간으로 산출하면,
(1) 최소: 6번 비교 --> 6 x 10마이크로초 --> 60마이크로초
(2) 최대: 60번 비교 --> 60 x 10마이크로초 --> 600마이크로초 --> 0.6미리초
100만개의 단어중에서 하나의 단어를 검색할때 최대 0.6미리초만에 검색해 낼 수 있다는 것인데,
대단하지 않나요?
BTree 알고리즘은 1970년에 보잉사에서 연구원으로 일하던 R.Bayer에 의해서 이미 개발된 알고리즘입니다.
(Bayer의 발표 논문은 제가 http://www.kernel.bz/db/02/db0201.htm 에 번역해 두었습니다)
그런데 BTree는 몇가지 단점을 가지고 있었는데,
(1) 할당된 메모리의 50% 정도만 사용함 --> B*Tree로 개선됨.
(2) 포인터와 데이터가 하나의 노드에 있어 알고리즘 효율이 다소 떨어짐 --> B+Tree로 개선됨.
이렇게 개선되어 왔습니다. 또 어떤 알고리즘들이 있을까요?
저의 관심사는 휴대용(스마트)기기에 영어단어사전을 구축하고 영어번역학습기를 구현하는 것이고,
더 나아가 자연어 기계 번역에 도전하려 합니다. 자연어 번역은 하면 할수록 재미있는 주제인듯 합니다.
컴퓨터에 구현할 수 있는 고급 알고리즘 지식들을 총동원하여 응용개발 및 개선해야 할듯합니다.
휴대용기기에서 상용 DBMS(오라클,MSSQL,MySQL,Sybase...)을 포팅하여 사용하는것은 많은 부하가 걸립니다.
그래서 영어번역학습 맞춤형 자료구조와 알고리즘을 구현하는것이 중요하고 어느정도 구현하였습니다.
앞으로 꾸준히 그 결과물들을 공유해 나갈 예정입니다.
저의 발제에 관심 있거나, 좋은 알고리즘들을 같이 학습하고 서로 검증해 보고자 하는 결과물이
있다면 서로 연락하고 토론했으면 합니다.
from 알지비(rgbi3307(at)nate.com) on the www.kernel.bz
From:
*알지비 (메일: rgbi3307(at)nate.com)
*커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))
그냥 몇가지..
물론 휴대용 기기에 오라클이나 mysql같은 무거운 디비는 어렵겠지만 sqlite정도는 괜찮지 않을까요? 이런 디비들 인덱스는 모두 B트리 기반인데요.
그리고 그냥 영어 단어를 정렬한 상태로 저장해 놓고 쓰면 안되나요? 뭐 영어단어가 맨날 업데이트되는 것도 아닌데 그냥 정렬 된 상태로 파일에 저장하고 메모리에 로드할때 순서대로 로드 한 상태에서 사용하면 이진트리라도 충분할것 같은데.
Cuckoo hashing이라는 방법도 쓰인다고
Cuckoo hashing이라는 방법도 쓰인다고 들었습니다.
http://en.wikipedia.org/wiki/Cuckoo_hashing
이 방법을 사용할 경우 사전을 생성하는데 상당한 시간이 걸리고
가끔 사전 생성이 불가능한 경우도 있습니다만,
일단 사전의 lookup이 O(1)인지라 = _=)...
그리고 그냥 태클 걸자면...
명령어 하나당 100클럭은 너무 오버가 심하신데요... 최신 컴퓨터에서는 파이프라이닝이 잘 되어 거의 1클락에 명령어 하나씩 처리할 수 있습니다. 게다가 왠만한 CPU에서는 4바이트에서 8바이트를 한꺼번에 비교할 수 있습니다. 영어단어가 ASCII내지는 UTF-8인코딩이라면 한번에 4~8글자를 비교 할 수 있다는 뜻이죠. 따라서 대강 생각하면 선형찾기 알고리즘이라도 1GHz CPU에서 100만개의 영어단어는 아무리 많이 잡아도 0.5초 안에 비교 할 수 있을것 같습니다.
맞는 지적 이십니다.
명령어 하나당 100클럭은 너무 많습니다.
수의 크기를 좀더 명확히 비교해 보기 위해서 클럭의 편차을 좀 많이 잡았습니다.
그러나 저의 계산논리에는 문제가 없을듯... 이것을 지적해 주실 정도면 제 생각을 이미 이해하고 계실듯합니다. 단, 파이프라이닝에서 1클럭에 명령어 하나씩 처리한다고 언급하셨는데, 파이프라이닝을 처음으로 접하는 사람은 좀 오해할 수도 있겠습니다. 파이프라이닝은 1클럭에 명령어 하나씩 처리한다기 보다, 20클럭안에 연산(ADD), 비교(CMP), 저장(MOV) 명령등를 중첩시켜 처리하도록 CPU 논리회로를 설계한 기법입니다.
From:
*알지비 (메일: rgbi3307(at)nate.com)
*커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))
이것 또한 파이프라이닝에 대한 오해가 될 수 있겠는데요...
파이프라이닝은 꼭 몇클럭이다가 중요한 것이 아니라 명령 하나를 여러 단위로 쪼개고 그 명령의 각 부분을 독립적으로 처리 할 수 있게 해준 것 입니다. 예전에 프레스캇 같은 경우 파이프라인 깊이가 31단계 까지 갔었고요, 결국 발열때문에 포기를 하게 되었죠. 요즘 CPU들이 20단계정도 합니다.
결국 파이프 라인의 목적은 각각의 단계를 독립적으로 수행함으로써 전체적인 명령어를 동시에 수행하도록 하겠다는 것 입니다. 하지만 data dependency때문에 speculation등이 많이 필요한 작업입니다. 하지만 결국 파이프라이닝을 하는 이유는 같은 클럭에 보다 많은 명령어를 처리하기 위한 방법입니다. 요즘 최신 CPU같은 경우 CPI(clock per instruction)이 평균적으로 1에 가까이 가게 됩니다. 즉, 한 명령어를 1클락에 처리한다는 뜻이죠. 저는 이러한 맥락으로 말한 것 입니다.
사전탐색에는 TRIE가 제일 무난한 듯
TRIE가 B-Tree보다 간단하면서도 사전 탐색에 적합한 맞춤형 알고리즘이라고 생각합니다.
탐색 횟수가 사전의 크기에 좌우되는 것이 아니고 탐색 문자열의 길이에 의해 좌우되기 때문에
8문자의 단어를 탐색할 경우 최대 8번만 탐색하면 되기 때문에 속도에 있어서도 별 문제가 없고
알고리즘 구조 자체가 사전과 가장 부합되는 알고리즘이 아닐까 합니다.
TRIE는
Binary Search Tree와 Red-Black Tree에서 파생된 알고리즘으로
브랜치(branch)의 수가 3개인듯 합니다.(BTree의 오더가 3인것과 같은 방식)
TRIE는 알파벹을 인덱스화 해서 영어단어와 같은 문자열을 검색하기에 좋겠으나,
영어 알파벹 26개 조합 순열을 모두 인덱스화 하여 브랜치(branch)에 저장해야 하는 부담이 있을듯합니다.
알파벹 26개를 조합하는 경우의 수는 20!(팩토리얼)로 상당히 많습니다.
제 생각에는 BTree의 단점을 보완한 B+Tree을 사용하면
BST의 장점 + RBT의 장점 + TRIE의 장점을 모두 활용할 수 있을듯...
From:
*알지비 (메일: rgbi3307(at)nate.com)
*커널연구회(http://www.kernel.bz/) 내용물들을 만들고 있음.
*((공부해서 남을 주려면 남보다 더많이 연구해야함.))
TRIE에 대해서...
제가 잘못 윗 글을 잘못 이해 한 것을 수도 있으나, 제가 생각하기에는 윗글은 TRIE에 대해 잘못 이해한 글로 보입니다.
TRIE는 branch수와는 상관 없습니다. 그리고 Binary Search Tree나 Red-Block Tree에서 파생된 것이 아니라, Radix Sort의 일종입니다.
또한, 26개의 조합 순열을 인덱스화해서 저정할 필요도 물론 없습니다.
그리고, 제가 알기로도, wyb330님 말씀대로, 사전같은 검색에는 TRIE가 최고라고 알고 있습니다.
휴대 기기용 영어 전자 사전 만들어 본
휴대 기기용 영어 전자 사전 만들어 본 사람입니다.
이상적으로 Hash 를 사용할 경우 O(1) 이 걸리겠지만, 실제로는 메모리 사용량, 코딩의 복잡도
등으로 인해서 Binary search 를 사용했습니다.
Binary Search 를 사용할 경우 2^20 = 1024*1024 = 1M 즉, 20번의 문자열 비교면 충분합니다.
데이타 구조도 간단해서 사전 데이타는 텍스트 형태로 압축해서 저장하고, 각 단어의 위치의 인덱스 정보
파일만 별도로 저장하면 됩니다. DB 고 뭐고 다 필요 없습니다.
데이타가 사용자 기기에서 동적으로 변화하지 않을 경우 binary search 면 충분합니다.
15년전 200LX ( http://en.wikipedia.org/wiki/HP_200LX ) 라는 기기였는데, 단어수가 10만인가 30만인 상황에서
사용자가 단어를 입력하면 실시간으로 검색해서 내용을 보여줄 정도의 속도는 나왔습니다.
======== 서명 =======
주거지는 www.indidev.net 입니다.