Эффективные числовые массивы с множественной точностью
Numpy - это библиотека для эффективных числовых массивов.
mpmath, при поддержке gmpy, является библиотекой для эффективных многоточных чисел.
Как мне их эффективно соединить? Или уже эффективно просто использовать массив Numpy с числами mpmath?
Не имеет смысла просить "столь же эффективно, как нативные операции с плавающей запятой", но вы можете попросить, чтобы он был близок к эффективности эквивалентного кода C (или, в случае неудачи, кода Java/C#). В частности, эффективный массив чисел с множественной точностью будет означать, что вы можете выполнять векторизованные операции и не искать, скажем, __add__
миллион раз в глобальном переводчике.
Редактировать: Для близкого избирателя: Мой вопрос об эффективном способе их объединения. Ответ в возможном дубликате конкретно указывает на то, что наивный подход неэффективен.
Наличие пустого массива dtype=object может ввести в заблуждение, потому что мощный мощный numpy механизм, который делает операции со стандартными dtypes суперскоростными, теперь позаботится о python-операторах объекта по умолчанию, а это означает, что скорости не будет. больше не
3 ответа
Отказ от ответственности: я утверждаю gmpy2
, Следующие тесты были выполнены с версией разработки.
a
а также b
1000 списков элементов, содержащих псевдослучайный gmpy2.mpfr
значения с 250 битами точности. Тест выполняет поэлементное умножение двух списков.
Первый тест использует понимание списка:
%timeit [x*y for x,y in zip(a,b)]
1000 loops, best of 3: 322 µs per loop
Второй тест использует map
Функция для выполнения цикла:
%timeit list(map(gmpy2.mul, a, b))
1000 loops, best of 3: 299 µs per loop
Третий тест - реализация C понимания списка:
%timeit vector2(a,b)
1000 loops, best of 3: 243 µs per loop
В третьей попытке vector2
пытается быть хорошо управляемой функцией Python. Числовые типы обрабатываются с использованием gmpy2
правила преобразования типов, выполняется проверка ошибок и т. д. Проверяются настройки контекста, создаются ненормальные числа, если требуется, возбуждаются исключения, если это необходимо, и т. д. Если вы игнорируете все улучшения Python и предполагаете, что все значения уже gmpy2.mpfr
Я смог сократить время с четвертой попытки:
%timeit vector2(a,b)
10000 loops, best of 3: 200 µs per loop
Четвертая версия не выполняет достаточную проверку ошибок для общего использования, но возможна версия между третьей и четвертой попытками.
Можно уменьшить накладные расходы Python, но с увеличением точности эффективная экономия уменьшается.
Текущий проект - это qd, который сможет встраивать высокоточные числа в массивы Numpy, используя фиксированный размер в памяти его значений. Прямо сейчас, тип доступен для Numpy, но еще не как dtype; однако вы уже можете использовать его с объектом dtype.
(Если вы хотите посмотреть, как будет выглядеть dtype, вы можете уже раскомментировать соответствующую строку для его компиляции с поддержкой Numpy; это должно сработать, если у вас есть взгляд, но еще не реализована какая-либо функция; следующий выпуск должен быть в сентябре или октябрь).
Насколько мне известно, не существует библиотеки Python, которая поддерживает операции векторизованного массива с несколькими значениями точности. К сожалению, не существует особенно эффективного способа использовать значения с множественной точностью в numpy ndarray, и это крайне маловероятно, что когда-либо будет, поскольку значения с множественной точностью несовместимы с базовой моделью массива numpy.
Каждый элемент в numpy ndarray с плавающей запятой занимает одинаковое количество байтов, поэтому массив может быть представлен в терминах адреса памяти первого элемента, размеров и регулярного смещения (или шага) байта между последовательными элементами массива.
Эта схема имеет существенные преимущества в производительности - смежные элементы массива расположены по соседним адресам памяти, поэтому последовательное чтение / запись в массив выигрывает от лучшей локализации ссылки. Разметка также очень важна для удобства использования, поскольку позволяет выполнять такие операции, как работа с представлениями одного и того же массива без создания новых копий в памяти. Когда вы делаете x[::2]
на самом деле вы просто удваиваете шаг по первой оси массива, так что вы обращаетесь к любому другому элементу.
В отличие от этого, массив, содержащий значения множественной точности, должен содержать элементы неравного размера, поскольку значения с более высокой точностью занимают больше байтов, чем значения с низкой точностью. Массив с множественной точностью, следовательно, не может регулярно перемещаться, и теряет преимущества, упомянутые выше.
Помимо проблем с построением массивов, даже простая арифметика для скаляров с множественной точностью, вероятно, будет намного медленнее, чем для скаляров с плавающей запятой. Почти все современные процессоры имеют специализированные блоки с плавающей запятой, тогда как арифметика с множественной точностью должна быть реализована в программном, а не аппаратном обеспечении.
Я подозреваю, что эти проблемы с производительностью могут быть в значительной степени причиной того, почему еще нет библиотеки Python, обеспечивающей нужную вам функциональность.