2014-04-14 15 views
5

Nel seguente programma, rimuovendo la rigadefclass informazioni tipo per prestazioni

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

rende esecuzione aumentare il tempo di più di un fattore 3, utilizzando SBCL. Le informazioni sul tipo fornite nella macro defclass tramite :type non sembrano avere alcun impatto sulle prestazioni.

(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))) 

Come posso avere lo stesso beneficio delle prestazioni, senza dover dichiarare il arr slot di un simple-array bit ogni volta che lo uso? Quest'ultimo è particolarmente fastidioso dal momento che (per quanto ho scoperto) è necessario introdurre un binding tramite let o simili ogni volta; Non posso semplicemente scrivere (slot-value inst 'arr) nel posto in cui ho bisogno.

risposta

5

Primo di tutto, questa è una domanda specifica di SBCL, è possibile ottenere una risposta migliore nell'elenco degli utenti di SBCL. Diversi compilatori eseguono diverse ottimizzazioni e la maggior parte ignora almeno alcune dichiarazioni.

Secondo, è consigliabile effettuare il binding arr perché lo si utilizza due volte.

Terzo, è possibile utilizzare the se si vuole evitare di lasciare-bind:

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

Quarto, se si desidera che il compilatore di dedurre il tipo, utilizzare un lettore specifico invece di 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 dovrebbe consentire al compilatore di dedurre il tipo di valore più facile, ma (come tu stesso hai scoperto!) potrebbe essere necessario dichiarare il tipo restituito:

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

La ragione è, apparentemente, che SBCL ignora dichiarazioni di tipo slot.

+0

L'utilizzo di un lettore era una buona idea, ma non ha funzionato direttamente per me. Ciò che ha funzionato, tuttavia, è un lettore più il seguente, usando i nomi delle classi e delle funzioni: '(declaim (ftype (function ((c)) (simple-array bit)) c-arr))'. Con questo posto, anche il ': tipo' può essere omesso, così come' (declare (tipo class-1 inst)) '. –

+0

Probabilmente dovrebbe essere '(declaim (ftype (function (c) (simple-array bit)) c-arr))'. Entrambi sembrano funzionare, non sono sicuro del perché. Non ho usato quella forma prima. –

4

L'aggiunta di informazioni sul tipo ha effetti diversi a seconda del compilatore utilizzato e dei livelli di ottimizzazione effettivi.

Per un compilatore ottimizzato che potrebbe assomigliare a questo:

  • alcuna informazione: operazioni generiche, ragionevolmente veloce
  • tipo di dichiarazione a disposizione: aggiunto le operazioni per verificare la presenza di questo tipo specifico durante l'esecuzione -> più lento
  • dichiarazioni di tipo disponibili, ottimizzazione elevata e bassa sicurezza: NESSUNA operazione aggiunta per il controllo del tipo in fase di esecuzione, codice specializzato generato per questo tipo -> POSSIBLY FASTER

Alcuni compilatori ignorano anche le dichiarazioni di tipo per gli slot CLOS. Se non lo fanno, ci sono ancora due varianti: 1) sicurezza significa aggiunta di runtime e 2) bassa sicurezza e alta velocità significa istruzioni specializzate generate

Riepilogo: dichiarazioni di tipo possono aggiungere sovraccarico di runtime con elevata sicurezza a causa di tipo aggiunto controlli. Tipi di dati specializzati non necessariamente più veloci con bassa sicurezza e alta ottimizzazione.

Problemi correlati