Non ci hai detto quanti bit per pixel usi. Io ad esempio sto lavorando su immagini da 12 bit per pixel (che opencv mi scala a 16 all'apertura).
Inoltre, stai usando qualche compressione? Lossy or lossless?
Inoltre, 260^2 * 311 * 4 byte (assumendo siano float32) / 1024 /1024 fa circa 80 MB a immagine. Confermi?
Questa cifra e' ancora gestibile, direi.
Ora ..
> Per motivi computazionali il mio codice necessita di implementare una matrice con 21 milioni di righe e migliaia di colonne
Qua pero' non si capisce ogni colonna di questa matrice cosa e'.
1) una immagine delle N? Quindi hai una unica matrice di P pixel x N immagini (righe x colonne)?
2) Oppure le altre colonne dopo la prima sono altri dati associati all'immagine? Perche' se e' questo il caso, ossia le altre colonne sono metadati, probabilmente non saranno dense, quindi una matrice sparsa potrebbe aiutare; dipende sempre pero' da cosa devi farci dopo pero'.
Nel caso 1 della singola matrice, e' semplice: lavora temporaneamente a blocchi, ossia su sottomatrice P x M, dove M immagini < N, in modo che la singola matrice ci stia tutta in memoria, e poi ti sposti alle M immagini seguenti finche' non hai macinato tutte le N immagini.
Nel caso 2, avrai N matrici; lavora su M matrici < N immagini.
> Esiste un modo per gestire la memoria ram allocabile in un interprete python?
Cosa intendi con questo? Python da solo continua a chiedere memoria al sistema operativo, finche' questo non gli risponde picche quando l'ha finita.
> Forse in questo caso potrei cavarmela utilizzando le matrici sparse, ma questo metodo è oneroso dal punto di vista computazionale
Certo, lavorarci sopra e' oneroso, ma e' meglio che non poterci lavorare perche' vai OOM, convieni?
Io cercherei di ridurre in ogni caso le dimensioni del problema.
Magari usando un'immagine a minore qualita'?
Oppure riducendo le colonne della/e matrice/i?
Oppure scalando in verticale, se pensi che il problema possa stare dentro limiti di macchine moderne (esistono macchine con 1 TB di ram che puoi usare su aws, se devi solo lavorarci sopra poche ore costa un paio di euro -- dai un occhio anche alle spot instances), oppure puoi scalare in orizzontale su piu' nodi, usando cose tipo spark o layer di comunicazione tipo MPI (ma qua puo' diventare complessa la cosa). Il vantaggio dello scalare in verticale e' che se hai tutto in memoria eviti di dover caricare ogni volta da disco e sprecare preziosi cicli CPU.
Consiglio di implementare una strategia di checkpointing, perche' vuoi evitare di ricalcolare cose gia' fatte.