Улучшение производительности сложных логических условий на массивах numpy - PullRequest
1 голос
/ 24 марта 2019

Мне нужно оценить множество логических условий для большого двумерного массива "NUMPY" и собрать общий результат в массив логических значений "RESULT".

Простой пример, где все условия связаны с оператором AND:

РЕЗУЛЬТАТ = cond1 (NUMPY) и cond2 (NUMPY) & cond3 (NUMPY) & ....

Я бы хотел понять, есть ли способ оптимизировать производительность.

Например, в этом случае, если первое условие (cond1) имеет значение False для большинства значений в массиве NUMPY, это будет пустой тратой ресурсов на оценку всех других условий для этих значений, поскольку условия AND в любом случае сгенерируют False в окончательном массиве RESULT.

Есть идеи?

1 Ответ

1 голос
/ 24 марта 2019

Вы можете сделать короткое замыкание вручную, хотя я должен добавить, что, вероятно, оно того стоит только в довольно экстремальных случаях.

Вот пример 99 цепных логических и.Короткое замыкание осуществляется либо с помощью ключевого слова where, либо с использованием необычной индексации.Второй, но не первый, дает приличную скорость для этого примера.

import numpy as np

a = np.random.random((1000,))*1.5
c = np.random.random((100, 1))*1.5

def direct():
    return ((a+c) < np.arccos(np.cos(a+c)*0.99)).all(0)

def trickya():
    out = np.ones(a.shape, '?')
    for ci in c:
        np.logical_and(out, np.less(np.add(a, ci, where=out), np.arccos(np.multiply(np.cos(np.add(a, ci, where=out), where=out), 0.99, where=out), where=out), where=out), out=out, where=out)
    return out

def trickyb():
    idx, = np.where((a+c[0]) < np.arccos(np.cos(a+c[0])*0.99))
    for ci in c[1:]:
        idx = idx[(a[idx]+ci) < np.arccos(np.cos(a[idx]+ci)*0.99)]
    out = np.zeros(a.shape, '?')
    out[idx] = True
    return out

assert (direct()==trickya()).all()
assert (direct()==trickyb()).all()

from timeit import timeit

print('direct  ', timeit(direct, number=100))
print('where kw', timeit(trickya, number=100))
print('indexing', timeit(trickyb, number=100))

Образец прогона:

direct   0.49512664100620896
where kw 0.494946873979643
indexing 0.17760096595156938
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...