3

게으른 함수형 언어에서 링크 된 목록은 생성기와 유사한 의미를 가지며 최적화 컴파일러에서는 실제로 저장소에 사용되지 않을 때 오버 헤드를 완전히 제거 할 수 있다는 것을 알고 있습니다.링크 된 목록은 열망한 기능 언어로 실제적인 성능 이점을 갖고 있습니까?

그러나 열정적 인 기능 언어에서는 사용이 덜 어려워 보이지만 최적화는 더 어려워 보입니다. Scheme과 같은 언어가 기본 배열 표현으로 플랫 배열을 사용하는 좋은 성능의 이유가 있습니까?

단일 링크 된 목록을 사용하는 것이 명백한 시간 복잡성의 영향을 알고 있습니다. 필자는 열심히 단일 링크 된 목록을 기본 시퀀스 표현으로 사용하여 컴파일러 최적화를 고려한 실제 성능 결과에 대해 더 생각하고 있습니다.

+2

1) 단순함 2) 사소한 O (1) 앞자리 3) 공유 – Bergi

+0

@Bergi Simplicity는 실제로 "성능"이점이 아니지만 이유가됩니다. 나는 당신의 공유 지점을 이해할 수 있을지 잘 모르겠다. 불변성을 가정하면 플랫 어레이를 쉽게 공유 할 수 있습니다. – Textfield

+1

그러나 배열의 일부는 공유 할 수 없습니다. 목록은 꼬리를 공유 할 수 있습니다. – Bergi

답변

1

TL; DR : 성능 이점 없음!

첫 번째 Lisp는 데이터 구조로 cons (연결된 목록 셀)을 가지며 모든 용도로 사용되었습니다. Common Lisp와 Scheme은 오늘날 벡터를 가지고 있지만 기능적 스타일을 위해서는 좋은 일치는 아닙니다. 연결된 목록에는 누적 기 앞에 0 개 이상의 요소를 추가하는 재귀 적 단계가 하나있을 수 있으며 결국에는 반복 사이에 공유 된 목록이 있습니다. 이 연산은 하나 이상의 재귀를 수행하여 여러 버전이 모두 꼬리를 공유하게 만듭니다. 나는 공유가 링크드리스트의 가장 중요한 측면이라고 말한다. 미니 맥스 알고리즘을 만들어 연결 목록에 상태를 저장하면 상태의 변경되지 않은 부분을 복사하지 않고 상태를 변경할 수 있습니다.

작성자의 C++ Bjarne Stroustrup은 데이터 구조가 복잡하고 링크 된 목록에서 크기가 두 배가되는 페널티가 데이터 구조의 요소 절반을 이동해야하는 경우에도 쉽게 수행 할 수 있다고 언급했습니다. 이들은 이중으로 연결된 목록과 돌연변이 삽입물을 기억하고 있지만 대부분의 시간은 포인터를 선형 적으로 따라 가면서 모든 CPU 캐시가 누락되어 올바른 지점을 찾고 따라서 정렬 된 모든 O (n) 검색에 대해 언급합니다. 벡터를 더 잘 나열 할 수 있습니다.

목록에없는 목록에 많은 삽입을하는 프로그램이있는 경우 cons으로 CL 및 Scheme에서 할 수있는 트리가 더 좋은 선택 일 수 있습니다. 사실 Chris Okasaki의 모든 기능적 데이터 구조는 cons으로 구현할 수 있습니다. 하스켈에서 "변경 가능한"구조체는 대부분 비슷하게 구현됩니다.

Scheme에서 성능 문제가 발생하고 프로파일 링 한 후에 연결된 목록 작업을 배열로 대체하려고 시도하면 찾을 수없는 경우가 있습니다. 결국 모든 알고리즘 선택에는 장단점이 있습니다. 어떤 언어에서도 어려운 계산이 어렵습니다.

+1

C++ 배열/벡터는 기본적으로 _unboxed_ (메모리 - 압축)이므로 매우 빠르다는 것을 언급해야합니다. 따라서 실제로 캐시 미스없이 _elements_에 액세스 할 수 있습니다. 그러나 역동적 인 언어 (제한된 OO 동적 타이핑 포함)와 Haskell et al.일반적으로 포인터는 _ 배열 (_arrays)로만 사용할 수 있습니다. _O_ (_n_) 검색에서 요소를 찾아야하는 경우 캐시 미스가 발생합니다. 배열은 여전히 ​​연결 목록보다 빠르지 만 C++에서와 같이 큰 요인은 아닙니다. – leftaroundabout

+1

@leftaround about I concaur,하지만 우리는 이제 Haskell에서 unboxed vector를 가지고 있습니다. 이것들은 저수준의 안전하지 않은 프리미티브를 사용하여 정의되어야하고 unboxable 타입에 대해서만 정의되어야합니다. 그러나 성능은 C++에 더 가깝습니다. – chi

+0

@leftaroundabout 아니요, 속도는 주로 메모리 종속성을 제거하여 얻습니다. 포인터의 벡터는 연결된 값 목록보다 훨씬 빠릅니다. 메모리를 디레 퍼런 싱한다는 것은 대단히 잠재 성이있다. – Veedrac