2011-03-10 87 views
2

我對Python還很陌生,所以如果它很愚蠢,請原諒我這個問題。我找不到通過谷歌的答案...Python:如何保持跨越賦值的可變內存位置?

我在我的代碼中使用PyFFTW,它有一個計劃階段,在那裏你通過它的兩個變量(源/目的地),你的轉換從/到。然後,當您調用FFT時,將在確切的內存空間上進行操作,這些變量位於計劃階段。因此,需要完成對變量所做的任何操作,以便這兩個變量的內存位置不會改變。 我發現運營商*=,+=等,這些標準的數學運算符。 但是在我的程序中,我需要對變量應用一個函數,該函數應該將它返回到相同的內存位置。 如何做到這一點?

我最初使用切片以下列方式:

a[:] = func(a)[:] 

不過我才意識到,這是非常慢(我的代碼是慢約10%)。 那麼有人知道如何去做這件事嗎?

任何幫助非常感謝。提前致謝!

+0

總之,你絕對沒有力量在Python的內存細節。即使切片分配也可以輕鬆觸發重新分配,從而移動項目。有些實現可能會阻止整個世界,只是爲了在循環過程中感受到它的整個堆。 – delnan 2011-03-10 16:52:14

+0

嗨。我對這個想法感到非常驚訝,因爲這會讓PyFFTW的工作方式變得毫無用處,不是嗎?! – packoman 2011-03-10 18:48:58

+0

是的,這就是爲什麼我驚訝地聽到它的原因。如果你堅持使用CPython(因爲PyFFTW是一個C庫,它仍然受限於此),並且不會調整列表的大小,所以你相當不錯。只有更多的垃圾收集器和超出已經分配的大小(大多數數據結構有一些超分配,所以你可以在重新分配之前的一些項目),這可能會導致討厭的討厭問題(從段錯誤靜默地改變未使用的內存無聲數據損壞)。 – delnan 2011-03-10 18:52:06

回答

0

所以最終我無法找到一個令人滿意的解決問題的辦法。 我最初結束了使用上述

a[:] = func(a)[:] 

由delnan提出的解決方案和預分配一定大小的陣列。 對不起,添加這個作爲我的答案,因爲我無法弄清楚如何/如果有可能接受delnans評論作爲答案...

0

你的變量是一個可變類型,所以你的函數可以直接對它進行操作。

您仍然無法使用將要創建副本和/或創建新任務的函數和運算符(與您不能使用的相同),但函數參數的直接變化將會在功能之外可見。

+0

這是一個很好的觀點。我沒有考慮過 - 我猜是因爲來自MATLAB背景。我會嘗試,因爲我猜它也適合面向對象的編程要好得多......直到現在我總是從我的方法中返回「自我」,我認爲這不是風格明智的方式。 – packoman 2011-03-10 18:47:06

+0

嗨。我剛剛意識到我真的不能這樣做,你的建議是什麼,因爲在我的代碼中,我使用了Numpy的fftshift/ifftshift函數,所以我想這樣:a = fftshift(a) 現在我不想混亂fftshift的內部工作原理,所以我不能做直接變異。那麼你是否知道在不改變'a'的內存位置的情況下做任務的方式?我會很感激! – packoman 2011-03-11 17:27:08

0

這是你想要做的事嗎?

def time10(a): 
    """ multiple the elements by 10 in-place """ 
    for i in xrange(len(a)): 
    a[i] *= 10 
    # returning a is optional. I think it maybe useful for use to chain the operation 
    return a 

>>> a = range(10) 
>>> time10(a) 
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90] 
>>> a 
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90] 
>>> b = range(10) 
>>> time10(time10(b)) 
[0, 100, 200, 300, 400, 500, 600, 700, 800, 900] 
>>> b 
[0, 100, 200, 300, 400, 500, 600, 700, 800, 900] 
>>> 

您的原始代碼在數組返回後複製數組。這通常不是一個有用的練習,並且會影響您的運行時間較慢。

+0

嗨,謝謝你的回覆。其實我想要做的是相關的,是的。如果我要做一個* = b而不是a = a * b,它給了我相同的結果,但a * = b不會改變'a'的內存位置,而後者將會改變。所以問題是,我會如何做一些事情,如a = ifftshift(a)而不改變'a'的內存位置。 'ifftshift'是一個內置的函數,我不想重新實現,因此zerocrates建議的直接變異將不起作用。有任何想法嗎? – packoman 2011-03-11 17:22:19

0

如何使用本地值並將其引用到全局值。我想這可能做出更快...

global a 
a = [] 
def test(): 
    global a 
    b = [1,2,3,4] 
    a = b 
.... 

嗯..我也有cProfiler

來測試它