У кого какие мнения?
Просьба не указывать в качестве недостатков платность и закрытость исходников.
Интересно, какие недостатки наиболее раздражали в начале работы, и какие раздражают сейчас.
Мои ответы (для затравки):
1. Невозможность рестартов для параметров &key, &rest
2. Неумение дебаггера ходить по backquot-ам, не раскрывая их.
3. Возможность удалить текст в листенере (это я вроде сегодня поправил)
4. Чёрные квадраты вместо иконок через rdp (16-разрядный режим) - это я тоже уже почти поправил.
5. В степпере не пойми какой пакет.
6. Невозможность перейти из отладчика в степпер (хотя я понимаю, что это вовсе не легко реализовать).
Мне все понравилось, кроме цены. Среди лиспов, LispWorks - мой самый любимый. Приятный и простой в использовании. Надежный. Причем, Professional Version по моим наблюдениям надежнее, чем бесплатная Personal Edition. В первой просто больше патчей накатано.
Всех с Новым Годом!
Выложил на http://code.google.com/p/def-symbol-readmacro/ решения по п.1 (только для &key, причём перезапуск происходит с текущими значениями параметров), п.3 (почти работает, хотя, возможно, кое-где будет глючить), п.4 (сами иконки мне вендор запретил выкладывать, так что только код для вставки иконок в среду).
Ещё я понял, что не хватает возможности автоматически выстраивать окна среды на экране в зависимости от режима работы, подобно тому, как это делается в других IDE. Например, если из листенера запустили GUI отладчик, оба окна должны быть на экране, например, рядом, т.к. они работают скоординированно между собой. Опытному разработчику всё время приходится их тасовать, а для новичка неинтуитивно.
1) Изменение кодировки в настройках среды в "File encodings" влияют только на Editor, но не влияют на Stepper и Debugger (и наверное на другие окна)
Какое это имеет отношение к дебаггеру - я не совсем понял.
В степпере. Если написать строку атрибутов в файле - тоже не помогает?
Пример тут:
http://code.google.com/p/def-symbol-readmacro/source/browse/866.lisp
;;; -*- Encoding: (win32:code-page :id 866 :eof-style :crlf); -*-
Ещё скорость. LW работает дольше.Пример: перемножение 10000 векторов размерностью 2000 на SBCL у меня работает примерно 2 секунды, а LW и CCL - под 10.
> Ещё скорость. LW работает дольше.
Код в студию.
В теме про линейную алгебру есть. Собственно, я оптимизировал код на скорость, и решил запустить его в LW.Итак, функция перемножения векторов
(defun v-dot (v1 v2)
(let ((result 0.0)
(dim (length v1)))
(declare (type single-float result)
(type fixnum dim)
(type (simple-array single-float) v1 v2)
(optimize (speed 3) (safety 1)))
(dotimes (i dim)
(incf result
(the single-float (* (aref v1 i) (aref v2 i)))))
result))Ну и простой макрос для тестов:
(defmacro deftest (name times lambda-list &body body)
(with-gensyms (i)
`(defun ,name ,lambda-list
(time (dotimes (,i ,times)
,@body)))))Создаём тест:
(deftest test-vdot-my 10000 (dim)
(let ((a (make-array dim :element-type 'single-float :initial-element 0.0))
(b (make-array dim :element-type 'single-float :initial-element 0.0)))
(dotimes (i dim)
(setf (aref a i) (random 100.0))
(setf (aref b i) (random 100.0)))
(v-dot a b)))И тестим для вектора с размерностью 4000:
(test-vdot-my 4000)Результаты (ОС - 64-битная винда)
SBCL:
Evaluation took:
3.673 seconds of real time
3.666023 seconds of total run time (3.369621 user, 0.296402 system)
[ Run times consist of 0.107 seconds GC time, and 3.560 seconds non-GC time. ]
99.81% CPU
6,966,702,181 processor cycles
320,376,224 bytes consedClozure:
took 20,195,000 microseconds (20.195000 seconds) to run.
220,021 microseconds ( 0.220021 seconds, 1.09%) of which was spent in GC.
During that period, and with 4 available CPU cores,
20,155,329 microseconds (20.155329 seconds) were spent in user mode
15,600 microseconds ( 0.015600 seconds) were spent in system mode
320,320,064 bytes of memory allocated.Lisp Works:
User time = 19.219
System time = 0.015
Elapsed time = 19.327
Allocation = 2880237464 bytes
0 Page faults
С небольшим твикингом выжал за ~10 секунд (обрати внимание на специфичную оптимизацию для LW: (float 0)):
(in-package #:cl-user)(declaim (ftype (function ((simple-array single-float (*)) (simple-array single-float (*))) single-float)
v-dot))(defun v-dot (v1 v2)
(declare (optimize speed (safety 0) (debug 0) (float 0))
(type (simple-array single-float (*)) v1 v2))
(let ((result 0.0)
(dim (length v1)))
(declare (type single-float result)
(type fixnum dim))
(dotimes (i dim)
(incf result
(the single-float (* (the single-float (aref v1 i))
(the single-float (aref v2 i))))))
result))(defmacro deftest (name times lambda-list &body body)
(lw:with-unique-names (i)
`(defun ,name ,lambda-list
(time (dotimes (,i ,times)
,@body)))))(deftest test-vdot-my 10000 (dim)
(locally (declare (optimize speed (safety 0) (debug 0) (float 0))
(type fixnum dim))
(let ((a (make-array dim :element-type 'single-float :initial-element 0.0))
(b (make-array dim :element-type 'single-float :initial-element 0.0)))
(declare (type (simple-array single-float (*)) a b))
(dotimes (i dim)
(setf (aref a i) (the single-float (random 100.0)))
(setf (aref b i) (the single-float (random 100.0))))
(v-dot a b))))CL-USER>
(test-vdot-my 10000)Timing the evaluation of
(DOTIMES (#:I59121561 10000) (LOCALLY (DECLARE (OPTIMIZE SPEED (SAFETY 0) (DEBUG 0) (FLOAT 0)) (TYPE FIXNUM DIM)) (LET ((A (MAKE-ARRAY DIM :ELEMENT-TYPE (QUOTE SINGLE-FLOAT) :INITIAL-ELEMENT 0.0)) (B (MAKE-ARRAY DIM :ELEMENT-TYPE (QUOTE SINGLE-FLOAT) :INITIAL-ELEMENT 0.0))) (DECLARE (TYPE (SIMPLE-ARRAY SINGLE-FLOAT (*)) A B)) (DOTIMES (I DIM) (SETF (AREF A I) (THE SINGLE-FLOAT (RANDOM 100.0))) (SETF (AREF B I) (THE SINGLE-FLOAT (RANDOM 100.0)))) (V-DOT A B))))User time = 9.907
System time = 0.029
Elapsed time = 9.940
Allocation = 800203640 bytes
0 Page faults
А вообще CL не для этого. Нужно брать какую нибудь внешнюю оптимизированную библиотеку на Fortran или C и писать биндинги -- если по серьезному подходить к решению задачи.
И выделять в tight цикле большие массивы и затем их выбрасывать -- не правильно, я считаю.
Да это чисто синтетический пример. Я тесты на скорую руку набросал, в реале я массивы выкидывать не буду.
Я вообще хотел raytracer на лиспе написать. Начал искать либы для работы с векторами и матрицами и огорчился. Я понимаю, что CL для числодробилок как-то не очень (хотя компилятор умеет в быстрый код, да и есть куда оптимизировать). НО! почти во всех либах по работе с математикой используется CLOS. Да, код короче и красивее. Но проверка типов в рантайме очень тормозит программу. Ну вот зачем писать так? Я хочу найти простую библиотеку без всяких FFI для работы с векторами. Ведь можно писать на чистом CL довольно быстро, зачем везде пихать CLOS, не могу понять. К слову, тот же тест по перемножению векторов для библиотеки l-math у меня работает за 27секунд, против 4-х секунд на самописном варианте. Грусть-печаль. А ведь в рэйтрейсере быстрая работа с векторами и матрицами очень важна. Не хочу ждать минуту рендеринга, если можно ждать 10 секунд.
А вообще топик был про недостатки LW. Собственно, ясно видно, что он довольно тормозной. Даже с оптимизацией он проигрывает SBCL без неё.
> Грусть-печаль.
Я тоже писал свой велосипед. На альтернативы даже не смотрел. Но для серьезных вычислений я бы все же взял какой-нибудь GSL и написал обертки только для части, которая нужна сейчас.
Вот сейчас понадобилось мне распознавание образов, буду писать биндинги для OpenCV, причем может даже напишу удобную обертку-либу на C, которую потом заверну в FFI.
> Собственно, ясно видно, что он довольно тормозной.
Пусть LW немножко тормозмозной, зато стабильный по сравнению с глючным скорострельным SBCL.
Неспроста в ITA используют несколько лисп-систем. Поэт ому важно писать "кросс-лисп-системный" код.