Previous Entry Share Next Entry
SBCL, x86, SSE
R
love5an
Я тут подумал - неплохо бы приделать к 32битному SBCL SSE.

Но, тут все не так просто.
Первая проблема - SSE на x86, в отличие от x86-64 - фича совсем не обязательно присутствующая.
Поэтому, придется определять доступность SSE в рантайме.
Вот так, например:
(eval-when (:compile-toplevel :execute)

(sb-c:defknown %simd-info () (unsigned-byte 32))

(sb-c:define-vop (%simd-info-vop)
  (:translate %simd-info)
  (:results (info :scs (sb-vm::unsigned-reg)))
  (:result-types sb-vm::unsigned-byte-32)
  (:policy :fast-safe)
  (:generator
    0
    (sb-c::inst sb-vm::mov sb-vm::eax-tn 1)
    (sb-c::inst sb-vm::cpuid)
    (sb-c::inst sb-vm::and sb-vm::ecx-tn #x10180201)
    (sb-c::inst sb-vm::and sb-vm::edx-tn #x06800000)
    (sb-c::inst sb-vm::or  sb-vm::edx-tn sb-vm::ecx-tn)
    (sb-c::inst sb-vm::mov info          sb-vm::edx-tn)))

) ;;eval-when

(defun simd-info ()
  "(values MMX SSE SSE2 SSE3 SSSE3 SSE4.1 SSE4.2 AVX)"
  (let ((info (%simd-info)))
    (values (logbitp 23 info)
            (logbitp 25 info)
            (logbitp 26 info)
            (logbitp 0  info)
            (logbitp 9  info)
            (logbitp 19 info)
            (logbitp 20 info)
            (logbitp 28 info))))


Вторая проблема - непонятно, в какой именно момент определять доступность SSE.

При компиляции? А как тогда быть с переносимостью кода, в частности с переносимостью самого рантайма SBCL и его стандартной библиотеки?

При непосредственном использовании? Медленно.

Может быть, в момент запуска рантайма?

Если че, я делал simd математику в вопах, но это было на x64 и для типа регистра пользовался (complex double-float), они в x64 напрямую мапятся в xmm0-xmm9 :)

Что касается переносимости бинаря sbcl, то его и не было никогда. Даже два sbcl-я разных версий не открывают fasl-ы друг друга. И на разных машинах тоже надо все перекомпилировать.

Я летом допилил прошлогоднюю попытку Paul Khuong до некого работоспособного состояния, включая контриб, который экспортирует команды в виде функций:

https://github.com/angavrilov/sbcl/commits/sse/
https://github.com/angavrilov/cl-simd/commits/master/

Только я не знаю как довести это до включения в сам sbcl - разговоры в чате #sbcl ни к чему реальному пока не привели...

ia32 маст дай.

Ну, маст дай - не маст дай, а проблема тут, на самом деле, немного в другом. А именно - в наличии внутри одной архитектуры процессоров, реализующих разные подмножества инструкций. Вот появятся процессоры с каким-нибудь avx - и та же проблема вылезет и на x86_64.

На самом деле ИМХО единственный разумный способ реализации опциональной поддержки некоторого расширенного набора инструкций - это включение/отключение их поддержки через *features* при сборке компилятора (как, к примеру, включается/выключается поддержка нитей). Соответственно, для одной архитектуры мы сможем иметь компилятор поддерживающий расширенный набор инструкций (и не работающий на процессорах без него) и не поддерживающий, зато работающий на старых процессорах. И тут уже остаётся пользователю решать что ему важнее - бОльшая переносимость рантайма или более эффективный код.

Тут в общем как и с флагами gcc: хочешь эффективности - -O3 -march=native и вперёд, хочешь наибольшей переносимости - -march=i686 (или i386, если нужно совсем древнее тоже поддерживать).