Почему numpy.float16 нарушает функциональность OpenBlas/Atlas?

Хорошо, я знаю, что float16 не является настоящим примитивным типом, но он моделируется Python/numpy. Однако возникает вопрос: если это существует и Python позволяет использовать его при умножении массивов с помощью функции numpy.dot(), то почему OpenBlas (или ATLAS) не работает должным образом? Я имею в виду, что умножение работает, а параллельные вычисления — нет. Или, по-другому (на мой взгляд, лучше), почему Python/numpy позволяет использовать float16, если тогда мы не можем использовать расширенные функции, предлагаемые OpenBlas/ATLAS?


person f_ficarola    schedule 05.07.2014    source источник
comment
Я заметил, что scipy.ndimage.gaussian_filter1d (и функции, которые его используют) прерываются на np.float16. Не уверен, как этот тип данных закодирован, но ваша проблема, похоже, не единственная.   -  person eickenberg    schedule 05.07.2014


Ответы (1)


Numpy float16 — странный и, возможно, злой зверь. Это число с плавающей запятой половинной точности IEEE 754 с 1 битом знака, 5 битами экспоненты и 10 битами мантиссы.

Хотя это стандартное число с плавающей запятой, оно появилось недавно и широко не используется. Некоторые графические процессоры поддерживают его, но аппаратная поддержка не распространена в процессорах. Новые процессоры имеют команды для преобразования между 16-битными и 32-битными числами с плавающей запятой, но не поддерживают их непосредственное использование в математических операциях. Из-за этого, а также из-за отсутствия подходящих типов данных в распространенных языках нижнего уровня, 16-битное число с плавающей запятой используется медленнее, чем его 32-битный аналог.

Только несколько инструментов поддерживают это. Обычно 16-битное число с плавающей запятой рассматривается как формат хранения, который затем перед использованием преобразуется в 32-битное число с плавающей запятой.

Некоторые ориентиры:

In [60]: r=random.random(1000000).astype('float32')

In [61]: %timeit r*r
1000 loops, best of 3: 435 us per loop

In [62]: r=random.random(1000000).astype('float16')

In [63]: %timeit r*r
100 loops, best of 3: 10.9 ms per loop

В качестве общего использования не используйте его ни для чего другого, кроме как для сжатого хранилища. и даже тогда знайте о компромиссе:

In [72]: array([3001], dtype='float16') - array([3000], dtype='float16')
Out[72]: array([ 0.], dtype=float32)
person DrV    schedule 05.07.2014
comment
Таким образом, 16-битный формат с плавающей запятой не является стандартным форматом. Это неверно. Это двоичный тип IEEE 754 200816, очень стандартный формат. - person Mark Dickinson; 06.07.2014
comment
См. docs.scipy.org/doc/numpy/user/basics.types. .html, где это описано явно: знаковый бит, 5-битная экспонента, 10-битная мантисса. - person Mark Dickinson; 06.07.2014
comment
Упс. Я пересмотрю свой ответ! Спасибо. - person DrV; 06.07.2014
comment
Спасибо за доработку! - person Mark Dickinson; 06.07.2014
comment
@MarkDickinson: Нет ничего хорошего в том, чтобы оставлять на виду простую неверную информацию ... И теперь я многому научился, немного покопавшись в предыстории поплавка половинной точности. Итак, я и смущен (прежнее неведение), и счастлив (новое знание). И должен сказать вам теплое спасибо. - person DrV; 06.07.2014
comment
Да, действительно эта проблема связана с другой моей предыдущей проблемой умножения массивов (см. это: stackoverflow.com/questions/24490760/). Хотя я настроил свою систему для правильной работы с Atlas (сначала) и OpenBlas (затем), это умножение не использует параллельные вычисления, если я устанавливаю значения массива как float16 типы. Честно говоря, это сводило меня с ума... в конце концов я обнаружил, что это проблема примитивного типа. Я думаю, что документация numpy должна сообщать, что может работать, а что нет. - person f_ficarola; 06.07.2014
comment
@DrV: в любом случае, спасибо за ваш ответ и вклад (то же самое для Марка Дикинсона). Я оставлю этот вопрос открытым на некоторое время, просто чтобы посмотреть, есть ли другие вклады. - person f_ficarola; 06.07.2014