Мне нужна помощь в понимании и исправлении примечания компилятора SBCL, в котором говорится:
; in: DEFUN PRINT-SEARCH-PROGRESS-GRAPH
; (- (1+ WOULDWORK-PKG::*N*)
; (LENGTH WOULDWORK-PKG::*L*))
;
; note: doing signed word to integer coercion (cost 20), for:
; the first result of inline (signed-byte 64) arithmetic
Некоторая, возможно, важная справочная информация:
(optimize (debug 3))
(defparameter *N* 0)
(declaim (fixnum *N*))
(defparameter *L* nil)
(declaim (list *L*))
(type-of *N*) => BIT
Вы объявили *N* как FIXNUM, то есть целое число фиксированного размера; это эквивалентно (SIGNED-BYTE 64) в 64-битном SBCL. Но если его значение окажется MOST-POSITIVE-FIXNUM, (1+ *n*) может дать значение, которое не умещается в 64 бита, поэтому его придется преобразовать в INTEGER. Примечание предупреждает вас, что это преобразование может иметь место.
Если вы знаете, что он никогда не будет настолько высоким, чтобы это переполнение было необходимо, вы можете использовать THE:
(- (the fixnum (1+ *n*)) (length *l*))
Что касается первого исправления, переменная *N* должна быть fixnum, потому что я объявляю ее с помощью sb-ext:defglobal, чтобы включить параллельное обновление. Что касается второго исправления с использованием «fixnum», я получаю то же примечание компилятора, что и раньше.
Вероятно, это потому, что у (length *l*) нет причин быть фиксированным числом (следовательно, вычитание, вероятно, должно быть «общим»). Более того, вычитание двух фиксированных чисел все равно может привести к «бигнуму»: — вы можете обернуть каждое выражение в (the fixnum ...) — или объявить (возможно, локально) то, что вы знаете, например. (declare (type (integer 0 42) *N*)) если вы знаете точные границы *N* - в общем, напишите остальную часть программы и профилируйте, чтобы увидеть, имеет ли вообще отношение эта ОДНА операция к производительности.
Да, похоже, что есть потенциал для превышения самого отрицательного фиксированного номера. Перемещение «fixnum» в начало выражения работает, очевидно, потому, что sbcl может вычислить внутренние выражения. Цените идеи.
@Numbra: на самом деле в 64-битном SBCL (и я уверен, что и в 32-битном) length должен возвращать fixnum, и SBCL знает об этом (длина самого длинного списка — это fixnum, а array-dimension-limit — это fixnum .
Изменить (fixnum *N*) на (integer *N*)