Что происходит с указателями Numpy / Scipy, когда они копируются в локальную переменную? - PullRequest
4 голосов
/ 30 ноября 2011

Мне известно, что массивы numpy являются массивами указателей. И я знаю, что в python можно определять указатели. Но мне интересно, если я сделаю переменную равной элементу в числовом векторе, это все еще указатель или разыменование? Есть ли способ узнать или проверить это?

Пример

    import scipy
    vec = scipy.randn(10)
    vecptr = vec # vecptr is a pointer to vec
    vecval = scipy.copy(vec) # vecval is not a pointer.

    var = vec[3] # is var pointer or is it copied by value ???

    print(type(var)) # returns numpy.float64.  does this mean its a 1x1 numpy vec and therefore  a pointer ?

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

    v = self.viewCoefs[sz][sv][sa]

    gw = v[0]
    G0 = v[1]
    G1 = v[2]
    G2 = v[3]
    alpha0 = v[4]
    alpha1 = v[5]
    alpha2 = v[6]
    beta0 = v[7]
    beta1 = v[8]
    beta2 = v[9]
    beta3 = v[10]
    gamma0 = v[11]
    gamma1 = v[12]
    gamma2 = v[12]
    gamma3 = v[12]
    gamma4 = v[13]
    delta0 = v[14]
    delta1 = v[15]
    delta2 = v[16]
    delta3 = v[17]
    delta4 = v[18]
    delta5 = v[19]
    zeta_prime_0 = v[20]
    zeta_prime_1 = v[21]
    zeta_prime_2 = v[22]
    Gamma_prime_0 = v[23]
    Gamma_prime_1 = v[24]
    Gamma_prime_2 = v[25]
    Gamma_prime_3 = v[26]

Потому что у меня много таких, чтобы следовать

    p0 = alpha0 + alpha1*scipy.log(bfrac) + alpha2*scipy.log(bfrac)**2
    p1 = beta0 + beta1*scipy.log(bfrac) + beta2*scipy.log(bfrac)**2 + beta3*scipy.log(bfrac)**3
    p2 = gamma0 + gamma1*scipy.log(bfrac) + gamma2*scipy.log(bfrac)**2 + gamma3*scipy.log(bfrac)**3 + gamma4*scipy.log(bfrac)**4
    p3 = delta0 + delta1*scipy.log(bfrac) + delta2*scipy.log(bfrac)**2 + delta3*scipy.log(bfrac)**3 + delta4*scipy.log(bfrac)**4 + delta5*scipy.log(bfrac)**5

    subSurfRrs = g*(p0*u + p1*u**2 + p2*u**3 + p3*u**4)
    ## and lots more

Так что я хотел бы, чтобы значимые имена переменных не удваивали отпечаток моей памяти.

#

Хорошо, если я правильно понял, решение НЕ удвоить мою память:

    v = self.veiwCoefs[sz][sv][sa]

    gw = v[0:1]
    G0 = v[1:2]
    G1 = v[2:1]
    alpha0 = v[3:4]
    alpha1 = v[4:5]
    alpha2 = v[5:6]
    beta0 = v[6:7]
    beta1 = v[7:8]
    beta2 = v[8:9]
    beta3 = v[9:10]
    ## etc 

    p0 = alpha0[0] + alpha1*scipy.log(bfrac) + alpha2[0]*scipy.log(bfrac)**2
    p1 = beta0[0] + beta1[0]*scipy.log(bfrac) + beta2[0]*scipy.log(bfrac)**2 + beta3[0]*scipy.log(bfrac)**3

    ## etc

Ответы [ 2 ]

4 голосов
/ 30 ноября 2011

Это почти у вас есть, но вот как создать представление для одного элемента:

In [1]: import numpy as np

In [23]: v = np.arange(10)

In [24]: a = v[3:4]

In [25]: a[0] = 100

In [26]: v
Out[26]: array([  0,   1,   2, 100,   4,   5,   6,   7,   8,   9])

Здесь a - представление четвертого элемента v, поэтому при изменении a вы меняете соответствующую позицию в v.

1 голос
/ 01 декабря 2011

Представления очень полезны, и их правильное использование может помочь сэкономить немного памяти, но в вашем случае я не думаю, что представления являются подходящими. Хотя представление повторно использует базовые данные, я бы не назвал это указателем. Каждое представление является уникальным объектом ndarray, то есть оно имеет свои собственные свойства, например shape:

In [4]: a = np.arange(7)

In [5]: b = a[1:5]

In [6]: b.shape = (2,2)

In [7]: b
Out[7]: 
array([[1, 2],
       [3, 4]])
In [8]: a.shape
Out[8]: (7,)

поэтому, когда вы делаете b = a[0:1], вы создаете новый объект ndarray, который содержит один int / float / ... или что-то еще. Если вы хотите, чтобы у вас были значимые имена для каждого элемента вашего массива, вы, вероятно, не станете намного более эффективными, чем:

v = self.viewCoefs[sz][sv][sa]

gw = v[0]
G0 = v[1]
G1 = v[2]
G2 = v[3]
alpha0 = v[4]
## etc

При этом вы должны попытаться выяснить, существует ли лучший способ векторизации вашего кода, то есть попытаться записать ваш код как операции над массивами вместо операций над элементами массивов. Например, вы можете написать:

coefs = np.zeros((5,5))
lt = np.tril_indices(5)
coefs[lt] = self.viewCoefs[sz][sv][sa]

p = (coefs * scipy.log(bfrac)**[1, 2, 3, 4, 5]).sum(-1)
subSurfRrs = g*(p*u**[1, 2, 3, 4]).sum()

Векторизованный код может быть намного быстрее при использовании numpy. В этом случае мы также используем трансляцию Numpy, которая, как мне показалось, была очень запутанной, пока я не узнал ее немного лучше и не понял, насколько она полезна.

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