Производительность преобразования пикселей с использованием clojure и quil

Давайте предположим, что я хотел бы написать алгоритм ocr. Поэтому я хочу создать двоичное изображение. Используя clojure и quil, я придумал:

(defn setup []

  (load-pixels)

  (let [pxls (pixels)
             ]
    (letfn [(pxl-over-threshold? [idx] (if (> (red (aget pxls idx)) 128) true false))
            ]
           (time (dotimes [idx 25500] (aset pxls idx (color (rem idx 255)))))

           (time (dotimes [idx 25500] (if (pxl-over-threshold? idx)
                                          (aset pxls idx (color 255))
                                          (aset pxls idx (color 0)))))))
  (update-pixels))

(defn draw [])

(defsketch example
  :title "image demo"
  :setup setup
  :draw draw
  :size [255 100]
  :renderer :p2d)

;"Elapsed time: 1570.58932 msecs"
;"Elapsed time: 2781.334345 msecs" 

Код генерирует градации серого и затем перебирает все пиксели, чтобы установить их черным или белым. Он выполняет запрошенное поведение, но для этого требуется около 4,3 с (1,3-ядерное ядро). У меня нет ссылки, чтобы поставить 4,3 сек в контексте. Но если подумать об обработке большего изображения, это должно стать невероятно медленным.

Я делаю что-то ужасно неправильно или есть способ закрепить вещи? Способна ли комбинация clojure и quil быстрее преобразовывать пиксели или мне следует выбрать другой язык / среду?

Пожалуйста, дайте мне знать, если я делаю что-то странное в коде. Я все еще новичок в clojure.

Заранее спасибо.

1 ответ

Решение

Времена, которые вы взяли, не особенно значимы, потому что код еще не теплый. Вам нужно "прогреть" код, чтобы JVM JIT-компилировала его, и тогда вы должны начать видеть хорошую скорость. Вы должны взглянуть на Как тестировать функции в Clojure? (Вы должны использовать Критерий.)

Что касается вашего кода, вы используете массивы, так что это должно дать вам хорошую производительность. По стилю, два подвесных ] у вас действительно странно. Может быть, это просто ошибка форматирования? Обычно хорошо удалять как можно больше повторяющегося кода, поэтому я бы также изменил это

(if (pxl-over-threshold? idx)
  (aset pxls idx (color 255))
  (aset pxls idx (color 0)))

к этому

(aset pxls idx (color (if (pxl-over-threshold? idx) 255 0)))

Если вы чувствуете, что выглядишь слишком запутанно / сложно (я вроде как на грани того, считаю ли я это слишком трудным для чтения или нет), вы можете вместо этого написать это одним из следующих способов:

(let [c (if (pxl-over-threshold? idx) 255 0)]
  (aset pxls idx (color c)))

(->> (if (pxl-over-threshold? idx) 255 0) color (aset pxls idx))
Другие вопросы по тегам