2012-12-03 150 views
4

我正在使用緩存over here來加速一些相當重的處理。 lru_cache可以很好地工作,並且可以大大加快速度。但是,當我多進程每個進程創建它自己的單獨緩存,並且有8份相同的東西。這似乎沒有問題,直到盒子內存不足,結果發生壞事。理想情況下,我需要爲這個應用程序緩存300個左右,但8 * 300不適合我必須使用的7GB,而我認爲1 * 300會。如何共享緩存?

是否有所有進程的方式來共享同一緩存?

+0

Python的'multiprocessing'模塊對[共享流程之間的狀態(一部分http://docs.python.org/2/library/ multiprocessing.html#共享狀態之間的處理)。 –

+0

是一個進程外緩存的選項嗎?你可以在你的緩存狀態中使用pickle,並將它存儲在redis中嗎? – SingleNegationElimination

+0

@sam事實上,看起來'經理'可以共享一個'dict',我猜想這是lfu緩存在內部。我想我希望有人已經砍死那之前,以適應這個問題,所以我沒有;-) –

回答

4

我相信你可以使用一個Manager進程之間共享的字典。理論上應該可以爲所有函數使用相同的緩存。

然而,我認爲一個更理智的邏輯是讓一個進程通過在查詢緩存中查找它們來響應查詢,如果它們不存在,則將該工作委託給子進程,然後緩存結果返回它。你可以很容易地做到這一點與

with concurrent.futures.ProcessPoolExecutor() as e: 
    @functools.lru_cache 
    def work(*args, **kwargs): 
     return e.submit(slow_work, *args, **kwargs) 

注意work返回Future對象,消費者將不得不等待。 lru_cache將緩存未來的對象,以便它們自動返回;我相信您可以不止一次訪問他們的數據,但現在無法對其進行測試。

如果您不使用Python 3,則必須安裝concurrent.futuresfunctools.lru_cache的backported版本。

0

Doh。 Katrie的把我在正確的軌道上,我會實現這個問題的答案,但我傻,它甚至比實際更容易[此應用]:

父進程可以實例化對象(從它的中央緩存)和通obj實例入池處理作爲它的參數...

@utils.lru_cache(maxsize=300) 
def get_stuff(key): 
    return Stuff(key) 

def iterate_stuff(keys): 
    for key in keys: 
     yield get_stuff(key) # doh, rather than just yielding the key, yield the cached obj 

def process(stuff_obj): 
    # get_stuff(key) <-- do this in the parent, rather than the child. 
    stuff_obj.execute() 

def main(): 
    ... 
    keys = get_list_of_keys() 
    for result in pool.imap(process, iterate_stuff(keys)): 
     evaluate(result) 
    ...