Более быстрое возведение в степень сложных массивов в Python с помощью Arrayfire

Согласно документации по arrayfire pow, af.pow() в настоящее время поддерживает только полномочия (и корни ...) реальные массивы. Ошибка не возникает, но я обнаружил, что использование af.pow() со сложным вводом может вызвать огромную утечку памяти, особенно если в качестве ввода используются другие функции (например, af.pow(af.ifft(array), 2)).

Чтобы обойти это, я написал функцию complexPow ниже. Похоже, это работает для сложных массивов без утечки памяти, и быстрое сравнение показало, что моя функция complexPow возвращает те же значения, что, например, numpy.sqrt() и оператор **.

def complexPow(inData, power):
    for i in af.ParallelRange(inData.shape[0]):
        theta = af.atan(af.imag(inData[i])/af.real(inData[i]))
        rSquared = af.pow(af.real(inData[i]), 2.0) + \
                    af.pow(af.imag(inData[i]), 2.0)
        r = af.pow(rSquared, .5)
        inData[i] = af.pow(r, power) * (af.cos(theta*power) + \
                1j*af.sin(theta*power))
    return inData

Есть ли более быстрый способ выполнить параллельное поэлементное возведение в степень, чем этот? Я не нашел ни одного, но боюсь, что упускаю здесь хитрость ...


person Community    schedule 30.01.2017    source источник
comment
Это определенно похоже на ошибку. Можете ли вы сообщить об этом на github.   -  person aatish    schedule 31.01.2017
comment
Конечно. Я так и думал. Сделаю завтра; У меня есть минимальный рабочий пример, показывающий утечку памяти.   -  person    schedule 31.01.2017


Ответы (1)


Это немного быстрее без параллельного цикла for:

def complexPow(inData, power):
    theta = af.atan(af.imag(inData)/af.real(inData))
    r = af.pow(af.pow(af.real(inData), 2.0) + 
                af.pow(af.imag(inData), 2.0), .5)
    inData = af.pow(r, power) * (af.cos(theta*power) + \
                1j*af.sin(theta*power))
    return inData

Проведено 4000 итераций над массивом dtype=complex с размерами (1, 2**18) с использованием nvidia Quadro K4200, Spyder 3, Python 2.7, Windows 7:

Использование af.ParallelRange: 7,64 секунды (1,91 мс на итерацию).

Метод выше: 5,94 секунды (1,49 мс на итерацию).

Увеличение скорости: 28%.

person Community    schedule 31.01.2017