Common Lisp, asdf, тесты, система компиляции с разными уровнями оптимизации

Что мне действительно нужно, так это определения исходных тестов:

Предположим, у меня есть система asdf:

(defsystem simple-system
  :serial t
  :components ((:module "src"
                        :components
                        ((:file "0-package")
                         (:file "1-tests-stubs")
                         (:file "2-code") ...))))

И еще одна система для проверки первой:

(defsystem simple-system-tests
  :serial t
  :components ((:module "src"
                        :components
                        ((:file "0-package")
                         (:file "1-tests-real")
                         (:file "2-code") ...))))

Единственная разница между ними в том, что в simple-system у меня 1-tests-stubs, а в simple-system-tests у меня 1-tests-real. В 1-tests-stubs я определяю макрос (defmacro def-test (&rest _args) nil), который получает "настоящую" реализацию в 1-tests-real.

Теперь я хочу скомпилировать simple-system с (declare (optimize (safety 0) (debug 0) (speed 3))) и simple-system-tests с противоположным (declare (optimize (safety 3) (debug 3) (speed 0))).

Как я могу это сделать (куда поместить и как установить эти объявления общим способом для этих двух систем)?

Как я могу повторно использовать определение simple-system в simple-system-tests (чтобы не повторяться, перепечатывая все модули/компоненты)?

И я должен быть уверен, что все файлы перекомпилированы с разными уровнями оптимизации для каждой системы.

Также было бы здорово, если бы для каждой системы файлы перекомпилировались только в том случае, если они были изменены (Своя копия скомпилированных файлов для каждой системы?).


person Bad_ptr    schedule 17.08.2017    source источник


Ответы (3)


Оптимизация с низкой безопасностью.

Вообще я бы не рекомендовал компилировать всю систему (библиотеку или приложение) с нулевой безопасностью следующим образом:

(declare (optimize (safety 0) (debug 0) (speed 3)))

Использование нулевой безопасности в сочетании с объявлениями типов может изменить семантику программы, а ошибки могут вызвать сбой программы. Это может даже открыть дыры в безопасности.

Моя рекомендация для производственного кода такова:

  • оптимизируйте критичные по скорости части с speed = 3 и оставьте обычные настройки безопасности (2 или 3).

  • если для дальнейшего повышения скорости требуется низкий уровень безопасности, указывайте его только там, где он необходим. Common Lisp предоставляет локальные объявления функций, а также специальный оператор локально где можно дополнительно ограничить область кода, где применяются объявления.

Возможность изменения настроек оптимизации

* (defparameter *safety* 0)

Это не работает, потому что значения безопасности должны быть числами:

*SAFETY*
* (defun foo (a) (declare (optimize (safety *safety*))) (1+ a))
; in: DEFUN FOO
;     (OPTIMIZE (SAFETY *SAFETY*))
; 
; caught WARNING:
;   Ignoring bad optimization value *SAFETY* in: (OPTIMIZE (SAFETY *SAFETY*))
; 
; compilation unit finished
;   caught 1 WARNING condition

FOO

Но это работает, используя оценку времени чтения:

* (defun foo (a) (declare (optimize (safety #.*safety*))) (1+ a))
WARNING: redefining COMMON-LISP-USER::FOO in DEFUN

FOO

Можно также вставлять целые объявления:

* (defparameter *optimization-declaration* '(declare (optimize (safety 0))))

*OPTIMIZATION-DECLARATION*
* (defun foo (a) #.*optimization-declaration* (1+ a))
WARNING: redefining COMMON-LISP-USER::FOO in DEFUN

FOO
* 
person Rainer Joswig    schedule 18.08.2017

Уровни оптимизации

Вы можете попробовать использовать :around-compile:

(defsystem simple-system
  :serial t
  :around-compile (lambda (next)
                    (proclaim '(optimize (debug 3) 
                                         (safety 3)
                                         (debug 3)
                                         (speed 0)))
                    (funcall next))
  :components ((:module "src"
                        :components
                        (...))))

В документации сказано (выделено мной):

Используя этот хук, вы можете добиться таких эффектов, как: локальное переименование пакетов, привязка *readtables* и других переменных, управляющих синтаксисом, обработка предупреждений и других условий, провозглашение согласованных настроек оптимизации, сохранение информации о покрытии кода, поддержка метаданные о времени компиляции, установке счетчиков gensym и начальных чисел PRNG и других источниках недетерминизма, переопределении систем расположения источника и/или временных меток, проверке того, что некоторые побочные эффекты времени компиляции были должным образом сбалансированы и т. д.

Действие выполняется вокруг каждого файла, который компилируется в системе; вы можете скрыть значение :around-compile для всех файлов в модуле или для определенных файлов.

person coredump    schedule 18.08.2017

Надеюсь, это просто опечатка, что в этих примерах один и тот же файл 0-package используется двумя системами. Если это не так, вы сильно проиграете, и это будет только ваша вина.

person Faré    schedule 22.08.2017
comment
один и тот же файл 0-package используется двумя системами ‹ Что с этим не так? - person Bad_ptr; 22.08.2017