2017-11-23 15 views
1

수치 계산을 위해 SBCL (64 비트 v1.4.0)을 사용합니다.Common Lisp에서 float to pointer coercion 피하기

(defun add (a b) 
    (declare (optimize (speed 3) (safety 0))) 
    (declare (double-float a b)) 
    (the double-float (+ a b))) 

또한 ftype을 시도하고 같은 메모를 가지고 :

다음
note: doing float to pointer coercion (cost 13) to "<return value>" 

내가 사용하는 코드는대로 : 최적화를 활성화 한 후, 컴파일러 메모를 다음 나타납니다. 한편

, 메모 표시되지 않는 코드를 다음

(defun add-fixnum (a b) 
    (declare (optimize (speed 3) (safety 0))) 
    (declare (fixnum a b)) 
    (the fixnum (+ a b))) 

내가 두 번 플로트와 Fixnum이라는 폭 모두 64 비트 생각합니다. SBCL이 C 언어와 같은 레지스터를 통해 double float 값을 반환 할 수없는 이유는 무엇입니까? 그리고 인라인 확장없이 float에서 포인터 강제 변환을 피할 수있는 방법이 있습니까?

+0

https://groups.google.com/forum/#!topic/comp.lang.lisp/AsKvR0emFtU – Barmar

답변

7

문제는 Lisp 데이터가 동적으로 형식화되고 함수의 반환 값에 형식 정보가 포함되어야한다는 것입니다. 대부분의 구현에서 type 태그는 값의 하위 비트에 저장됩니다.

fixnum에 대한 특수 최적화를 허용합니다. 타입 태그는 모두 0이며 값은 타입 태그의 비트 수만큼 왼쪽으로 시프트 된 정수입니다. 이 값을 추가 할 때 결과에는 여전히 태그 비트에 0이 있으므로 일반 CPU 작업을 사용하여 값에 대해 산술을 수행 할 수 있습니다.

그러나 부동 소수점 값에는 작동하지 않습니다. CPU 작업을 수행 한 후에는 유형 태그를 값에 추가해야합니다. 이것은 "float to pointer coercion"이 의미하는 것입니다. (많은 언어로 된 더 일반적인 단어는 "boxing"입니다.)

호출자가 반드시 선언문에 액세스 할 수 없기 때문에 반환 형식을 선언해도이를 피할 수는 없습니다. Lisp를 사용하면 호출자를 호출하는 함수가 아닌 별도의 컴파일 단위로 호출자를 컴파일 할 수 있습니다.

INLINE을 선언하면 호출자가 반환하는 유형을 알고 있기 때문에 태그를 추가하지 않고 하드웨어 값을 직접 반환 할 수 있기 때문에이 작업을 수행 할 필요가 없습니다.

더 자세한 설명은이 고대 comp.lang.lisp thread에서 찾을 수 있습니다. CMUCL은 SBCL이 파생 된 것입니다 (경고의 표현이 정확히 동일 함을주의하십시오).

+0

대단히 감사합니다. SBCL과 다른 Common Lisp 인터프리터의 type tag 사양을 이해했으며 fixnum (실제로 62 비트의 SBCL) 케이스는 특별했습니다. 별도의 컴파일에 대한 귀하의 설명은 완전히 내 문제를 해결했습니다. 다시 감사합니다! – magnon