2014-04-14 19 views
5

Trong chương trình sau đây, loại bỏ dòngdefclass loại thông tin để thực hiện

(declare (type (simple-array bit) arr)) 

làm cho thời gian chạy tăng hơn gấp 3, sử dụng SBCL. Thông tin loại được cung cấp trong macro defclass qua :type có vẻ không ảnh hưởng đến hiệu suất.

(defclass class-1() ((arr :type (simple-array bit)))) 

(defun sample (inst) 
    (declare (type class-1 inst)) 
    (let ((arr (slot-value inst 'arr))) 
    (declare (type (simple-array bit) arr)) ;; 3x running time without 
    (map-into arr #'(lambda (dummy) (if (< (random 1.0) 0.5) 0 1)) arr))) 

(let ((inst (make-instance 'class-1))) 
    (setf (slot-value inst 'arr) (make-array 10000 :element-type 'bit)) 
    (loop for i from 1 to 10000 do (sample inst))) 

Làm thế nào tôi có thể có hiệu quả lợi ích tương tự mà không cần phải khai báo arr khe một simple-array bit mỗi khi tôi sử dụng nó? Cái sau đặc biệt khó chịu vì (theo như tôi đã tìm ra) được yêu cầu giới thiệu một ràng buộc qua let hoặc tương tự mỗi lần; Tôi không thể chỉ viết (slot-value inst 'arr) ở nơi tôi cần.

Trả lời

5

Đầu tiên là của tất cả, đây là câu hỏi cụ thể về SBCL, bạn có thể có câu trả lời hay hơn về danh sách người dùng SBCL. Trình biên dịch khác nhau làm tối ưu hóa khác nhau, và hầu hết bỏ qua ít nhất một số khai báo.

Thứ hai, bạn nên để ràng buộc arr vì bạn đang sử dụng nó hai lần.

Thứ ba, bạn có thể sử dụng the nếu bạn muốn tránh let-ràng buộc:

(the (simple-array bit) (slot-value inst 'arr)) 

Thứ tư, nếu bạn muốn trình biên dịch để suy ra các loại, sử dụng một đầu đọc cụ thể thay vì slot-value:

(defclass c() ((arr :type (simple-array bit) :reader c-arr))) 

(defun sample (inst) 
    (declare (type class-1 inst)) 
    (let ((arr (c-arr inst))) 
    (map-into arr #'(lambda (dummy) (random 2)) arr))) 

c-arr nên cho phép trình biên dịch để suy ra kiểu giá trị dễ dàng hơn, nhưng (như bạn đã khám phá ra chính mình!), bạn có thể cần để khai báo loại trả về:

(declaim (ftype (function (c) (simple-array bit)) c-arr)) 

Lý do rõ ràng là SBCL bỏ qua khai báo loại vị trí.

+0

Sử dụng trình đọc là một ý tưởng hay nhưng nó không hiệu quả với tôi. Tuy nhiên, những gì làm việc là một đầu đọc cộng với những điều sau đây, sử dụng tên lớp và hàm của bạn: '(declaim (ftype (function ((c)) (bit mảng đơn giản)) c-arr))'. Với điều này tại chỗ, ngay cả ': type' có thể được bỏ qua, cũng như' (khai báo (loại lớp-1 inst)) '. –

+0

Nó có lẽ nên là '(declaim (ftype (hàm (c) (bit mảng đơn giản)) c-arr))'. Cả hai dường như làm việc, tôi không chắc chắn tại sao. Đã không sử dụng hình thức đó trước đây. –

4

Thêm thông tin loại có các hiệu ứng khác nhau tùy thuộc vào trình biên dịch bạn sử dụng và mức tối ưu hóa nào có hiệu lực.

Đối với một trình biên dịch tối ưu hóa nó có thể trông như thế này:

  • không có thông tin: các hoạt động chung, tương đối nhanh
  • kiểu khai báo có sẵn: thêm các hoạt động để kiểm tra các loại hình cụ thể này trong thời gian chạy -> chậm
  • loại khai báo có sẵn, tối ưu hóa cao và an toàn thấp: KHÔNG có hoạt động bổ sung để kiểm tra kiểu khi chạy, mã chuyên biệt được tạo cho loại này -> POSSIBLY FASTER

Một số trình biên dịch cũng bỏ qua các khai báo kiểu cho các khe CLOS. Nếu họ không, có một lần nữa hai biến thể: 1) an toàn có nghĩa là kiểm tra thời gian chạy thêm và 2) an toàn thấp và tốc độ cao có nghĩa là hướng dẫn chuyên biệt tạo ra

Tóm tắt: loại khai báo có thể thêm thời gian chạy với an toàn cao do thêm loại kiểm tra. Các loại dữ liệu chuyên biệt không nhất thiết phải nhanh hơn với độ an toàn thấp và tối ưu hóa cao.

Các vấn đề liên quan