Ответ 1
Я чувствую вашу боль... Иногда вы в конечном итоге сохраняете несколько раз размер вашего массива в значениях, которые вы позже сбросите. При обработке одного элемента в массиве за раз это не имеет значения, но может убить вас при векторизации.
Я использую пример из работы для иллюстрации. Недавно я закодировал алгоритм, описанный здесь, используя numpy. Это алгоритм цветовой карты, который принимает изображение RGB и преобразует его в изображение CMYK. Процесс, который повторяется для каждого пикселя, выглядит следующим образом:
- Используйте самые важные 4 бита каждого значения RGB, как индексы в трехмерную таблицу поиска. Это определяет значения CMYK для 8 вершин куба внутри LUT.
- Используйте наименее значимые 4 бита каждого значения RGB для интерполяции внутри этого куба на основе значений вершин с предыдущего шага. Самый эффективный способ сделать это требует вычисления 16 массивов uint8s размером обрабатываемого изображения. Для 24-битного изображения RGB, которое эквивалентно необходимости хранения в x6 раза, чем изображение для его обработки.
Несколько вещей, которые вы можете сделать, чтобы справиться с этим:
1. Разделите и победите
Возможно, вы не можете обработать массив 1000x1000 за один проход. Но если вы можете сделать это с помощью python для цикла, повторяющего более 10 массивов размером 100x1000, он все равно будет бить на очень отдаленном итераторе python более 1 000 000 элементов! Это будет медленнее, да, но не так много.
2. Кэширование дорогостоящих вычислений
Это относится непосредственно к моему примеру интерполяции выше, и его сложнее встретить, хотя стоит держать его открытым. Поскольку я интерполирую на трехмерном кубе с 4 битами в каждом измерении, возможны только 16x16x16 возможных результатов, которые могут быть сохранены в 16 массивах 16x16x16 байт. Таким образом, я могу прекомпилировать их и хранить их с использованием 64 Кбайт памяти, а также искать значения один за другим для всего изображения, а не повторять одни и те же операции для каждого пикселя при огромной стоимости памяти. Это уже окупается для изображений размером до 64x64 пикселей и в основном позволяет обрабатывать изображения с x6 раз большим количеством пикселей без разделения массива.
3. Используйте dtypes
мудро
Если ваши промежуточные значения могут вписываться в один uint8
, не используйте массив int32
s! Это может превратиться в кошмар загадочных ошибок из-за молчаливого переполнения, но если вы будете осторожны, это может обеспечить большую экономию ресурсов.