2011-05-11 31 views
6

Aşağıdaki numpy kodunu göz önünde bulundurun:numpy: boolean indeksleme ve bellek kullanımı

A[start:end] = B[mask] 

Burada:

  • A ve B aynı sayıda sütun içeren 2B dizileridir;
  • start ve end skalerdir;
  • mask, 1D boole dizisidir;
  • (end - start) == sum(mask).

Prensip olarak yukarıdaki işlem, B öğelerini A'e doğrudan kopyalayarak O(1) geçici depolama kullanılarak gerçekleştirilebilir.

Bu gerçekten pratikte gerçekleşen mi, yoksa numpyB[mask] için geçici bir dizi mi oluşturuyor? İkincisi, bu ifadeyi yeniden yazarak bundan kaçınmanın bir yolu var mı?

cevap

2

Boole dizilerini bir dizin olarak kullanmak, fantezi endeksleme olduğundan, numpy'nin bir kopya oluşturması gerekir. Bellek sorunları yaşarsanız, bununla başa çıkmak için bir cython uzantısı yazabilirsiniz.

+0

+1. Üstünde olduğu bu tür döngülerdir. –

3

hattı

A[start:end] = B[mask] 

olacaktır - Python dili tanımına göre - ilk B seçilen satır içeren ve ek bellek işgal yeni bir dizi verimli, sağ tarafı değerlendirir. Bunu önlemek için ben farkındayım en verimli saf Python yolu açık döngü kullanmaktır:

from itertools import izip, compress 
for i, b in izip(range(start, end), compress(B, mask)): 
    A[i] = b 

Tabii bu çok daha az zaman verimli orijinal kod daha olacak, ancak yalnızca (Ç kullanan 1) ek bellek. Ayrıca itertools.compress()'un Python 2.7 veya 3.1 veya üstü sürümlerinde mevcut olduğunu unutmayın. Cython'u getirmek için

+1

Şüphesiz, "seçilen B satırlarını içeren ve ek bellek işgal eden yeni bir dizi üretme", dizisizdir? Geri dönmek istediğini seçmek için B .__ getitem __() 'ye kalmış. Örneğin, 'maske' bir dilim 'olsaydı, bir vekil (görünüm) döndürüldü ve hiçbir kopya olmazdı. – NPE

+0

@aix: OP'ye göre, 'maske' tek boyutlu bir Boole dizisidir. Bir şey mi kaçırdım? –

+0

@aix: Oh, anladım. Dil sapması olan kısım biraz belirsizdir. Sadece "önce sağ tarafın değerlendirilmesi" bölümüne atıfta bulunmak istenmişti. –