← Архив: Common Lisp

5 самых отвратительных недостатков Lispworks

Author: · 10.12.2013 01:53
· original author: den73
У кого какие мнения?
Просьба не указывать в качестве недостатков платность и закрытость исходников.
Интересно, какие недостатки наиболее раздражали в начале работы, и какие раздражают сейчас.
Мои ответы (для затравки):
1. Невозможность рестартов для параметров &key, &rest
2. Неумение дебаггера ходить по backquot-ам, не раскрывая их.
3. Возможность удалить текст в листенере (это я вроде сегодня поправил)
4. Чёрные квадраты вместо иконок через rdp (16-разрядный режим) - это я тоже уже почти поправил.
5. В степпере не пойми какой пакет.
6. Невозможность перейти из отладчика в степпер (хотя я понимаю, что это вовсе не легко реализовать).
· original author: dsorokin
Мне все понравилось, кроме цены. Среди лиспов, LispWorks - мой самый любимый. Приятный и простой в использовании. Надежный. Причем, Professional Version по моим наблюдениям надежнее, чем бесплатная Personal Edition. В первой просто больше патчей накатано.
Всех с Новым Годом!
· original author: den73
Выложил на http://code.google.com/p/def-symbol-readmacro/ решения по п.1 (только для &key, причём перезапуск происходит с текущими значениями параметров), п.3 (почти работает, хотя, возможно, кое-где будет глючить), п.4 (сами иконки мне вендор запретил выкладывать, так что только код для вставки иконок в среду).
Ещё я понял, что не хватает возможности автоматически выстраивать окна среды на экране в зависимости от режима работы, подобно тому, как это делается в других IDE. Например, если из листенера запустили GUI отладчик, оба окна должны быть на экране, например, рядом, т.к. они работают скоординированно между собой. Опытному разработчику всё время приходится их тасовать, а для новичка неинтуитивно.
· original author: LinkFly
1) Изменение кодировки в настройках среды в "File encodings" влияют только на Editor, но не влияют на Stepper и Debugger (и наверное на другие окна)
· original author: den73
Какое это имеет отношение к дебаггеру - я не совсем понял.
В степпере. Если написать строку атрибутов в файле - тоже не помогает?
Пример тут:
http://code.google.com/p/def-symbol-readmacro/source/browse/866.lisp
;;; -*- Encoding: (win32:code-page :id 866 :eof-style :crlf);  -*-
· original author: memnek
Ещё скорость. LW работает дольше.Пример: перемножение 10000 векторов размерностью 2000 на SBCL у меня работает примерно 2 секунды, а LW и CCL - под 10.
· original author: lithp
> Ещё скорость. LW работает дольше.
Код в студию.
· original author: memnek
В теме про линейную алгебру есть. Собственно, я оптимизировал код на скорость, и решил запустить его в 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
· original author: lithp
С небольшим твикингом выжал за ~10 секунд (обрати внимание на специфичную оптимизацию для LW: (float 0)):
;;;; -*- Mode: Lisp; Syntax: ANSI-Common-Lisp; indent-tabs-mode: nil; external-format: utf-8; -*-

(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 и писать биндинги -- если по серьезному подходить к решению задачи.
· original author: lithp
И выделять в tight цикле большие массивы и затем их выбрасывать -- не правильно, я считаю.
· original author: memnek
Да это чисто синтетический пример. Я тесты на скорую руку набросал, в реале я массивы выкидывать не буду. 
Я вообще хотел raytracer на лиспе написать. Начал искать либы для работы с векторами и матрицами и огорчился. Я понимаю, что CL для числодробилок как-то не очень (хотя компилятор умеет в быстрый код, да и есть куда оптимизировать). НО! почти во всех либах по работе с математикой используется CLOS. Да, код короче и красивее. Но проверка типов в рантайме очень тормозит программу. Ну вот зачем писать так? Я хочу найти простую библиотеку без всяких FFI для работы с векторами. Ведь можно писать на чистом CL довольно быстро, зачем везде пихать CLOS, не могу понять. К слову, тот же тест по перемножению векторов для библиотеки l-math у меня работает за 27секунд, против 4-х секунд на самописном варианте. Грусть-печаль. А ведь в рэйтрейсере быстрая работа с векторами и матрицами очень важна. Не хочу ждать минуту рендеринга, если можно ждать 10 секунд.
А вообще топик был про недостатки LW. Собственно, ясно видно, что он довольно тормозной. Даже с оптимизацией он проигрывает SBCL без неё.
· original author: lithp
> Грусть-печаль.
Я тоже писал свой велосипед.  На альтернативы даже не смотрел.  Но для серьезных вычислений я бы все же взял какой-нибудь GSL и написал обертки только для части, которая нужна сейчас.
Вот сейчас понадобилось мне распознавание образов, буду писать биндинги для OpenCV, причем может даже напишу удобную обертку-либу на C, которую потом заверну в FFI.
· original author: lithp
> Собственно, ясно видно, что он довольно тормозной.
Пусть LW немножко тормозмозной, зато стабильный по сравнению с глючным скорострельным SBCL.
· original author: LinkFly
Неспроста в ITA используют несколько лисп-систем. Поэт ому важно писать "кросс-лисп-системный" код.