2010-03-04 4 views
4

대 --program는 Chez Scheme 코드의이 비트를 고려체즈 계획 할당 : --script

 
(import (chezscheme)) 

(define (list-enumerate ls val proc) 
    (let loop ((ls ls) (return? #f) (val val)) 
    (if (or (null? ls) 
      return?) 
     val 
     (call-with-values (lambda() (proc val (car ls))) 
      (lambda (return? val) 
      (loop (cdr ls) return? val)))))) 

(define (list-index ls proc) 
    (list-enumerate ls 
        0 
        (lambda (i elt) 
        (if (proc elt) 
         (values #t i) 
         (values #f (+ i 1)))))) 

(define n 100000) 

(define data (iota n)) 

(time (list-index data (lambda (elt) (= elt (- n 1))))) 

실행을 :

 
~ $ scheme --script ~/scratch/_list-enumerate-allocation-test-chez-a.sps 
(time (list-index data ...)) 
    no collections 
    3 ms elapsed cpu time 
    4 ms elapsed real time 
    8 bytes allocated 

와우, 그것은 단지 8 바이트가 할당 된보고합니다.

의 다시 --script 대신 --program 옵션을 사용하여 실행하자

 
~ $ scheme --program ~/scratch/_list-enumerate-allocation-test-chez-a.sps 
(time (list-index data ...)) 
    no collections 
    3 ms elapsed cpu time 
    3 ms elapsed real time 
    800000 bytes allocated 

이궁, 할당 된 800,000 바이트.

차이점은 무엇입니까?

에드

답변

4

여기에 응답 켄트 Dybvig에서 메모의 : 흥미로운 질문을의


합니다. REPL 의미론 변수 의 스크립트에서 정의 된리스트에서 열거하고 인덱스 등을 사용 --script으로 실행할 때

는 인라인 포함 시저 간 최적화를 저해 변경할 수있다. 그러나 이 --program으로 실행될 때 변수는 변경 불가능하므로 프로 시저 간 최적화가 가능합니다. 이 경우

는 --program 인라인 컴파일러리스트에 열거 신체리스트 인덱스의 본체 내의 람다 식 리스트 인덱스의 몸에 차례로리스트-열거 할 수있다. 최종 결과는 값이있는 호출자 제작자 표현식 내에 조건부 표현식입니다. 이로 인해 컴파일러는 조건부의 then 및 else 분기를 따라 코드 중복을 피하기 위해 소비자를위한 클로저를 작성합니다. 이 클로저는 목록 열거 루프를 통해 매번 생성되므로 여분의 할당 오버 헤드가 발생합니다. 그것이 바로 최적화의 방식입니다. 대부분 이길 수 있지만 때로는 잃게됩니다. 좋은 소식은 균형을 이루기 위해서 은 프로그램에서조차도 체중이 비쌉니다. 루프에 list-index (수정 된 코드는 아래에 있음)에 전화를 걸어 --program으로 코드가 약 30 % 빠르게 실행됩니다.

켄트


 
(import (chezscheme)) 

(define (list-enumerate ls val proc) 
    (let loop ((ls ls) (return? #f) (val val)) 
    (if (or (null? ls) 
      return?) 
     val 
     (call-with-values (lambda() (proc val (car ls))) 
      (lambda (return? val) 
      (loop (cdr ls) return? val)))))) 

(define (list-index ls proc) 
    (list-enumerate ls 
        0 
        (lambda (i elt) 
        (if (proc elt) 
         (values #t i) 
         (values #f (+ i 1)))))) 

(define n 100000) 

(define data (time (iota n))) 

(let() 
(define runalot 
    (lambda (i thunk) 
    (let loop ([i i]) 
     (let ([x (thunk)]) 
     (if (fx= i 1) 
      x 
      (loop (fx- i 1))))))) 

(time 
    (runalot 1000 
    (lambda() 
     (list-index data (lambda (elt) (= elt (- n 1))))))))