Contenuto principale

Risoluzione degli errori "Memoria esaurita"

R2026b

Problema

Quando il codice opera su grandi quantità di dati o non utilizza la memoria in modo efficiente, MATLAB® potrebbe generare un errore a causa di una dimensione irragionevole dell'array oppure potrebbe esaurire la memoria. MATLAB dispone di una protezione integrata dalla creazione di array troppo grandi. Ad esempio, questo codice genera un errore, poiché MATLAB non è in grado di creare un array con il numero di elementi richiesto.

A = rand(1e9);
Requested array exceeds the maximum possible variable size.

Per impostazione predefinita, MATLAB può utilizzare fino al 100% della RAM (esclusa la memoria virtuale) del computer per allocare memoria agli array; se la dimensione di un array dovesse superare tale soglia, MATLAB genererà un errore. Ad esempio, questo codice tenta di creare un array le cui dimensioni superano il limite massimo consentito per le dimensioni degli array.

B = rand(1e6);
Requested 1000000x1000000 (7450.6GB) array exceeds maximum array size preference (63.7GB). This might cause MATLAB to become
unresponsive.

Se si disattiva il limite di dimensione dell'array in MATLAB Workspace Settings, il tentativo di creare un array di dimensioni irragionevolmente grandi potrebbe causare l'esaurimento della memoria di MATLAB oppure impedire a MATLAB, o persino al computer, di rispondere a causa di un'eccessiva paginazione della memoria (ossia, lo spostamento delle pagine di memoria tra la RAM e il disco).

B = rand(1e6);
Out of memory.

Possibili soluzioni

A prescindere dal motivo per cui si raggiungono i limiti di memoria, MATLAB fornisce diverse soluzioni a seconda della situazione e degli obiettivi. Ad esempio, è possibile migliorare il modo in cui il codice utilizza la memoria, sfruttare strutture di dati specializzate come datastore e tall array, trarre vantaggio dalle risorse condivise all'interno di un cluster di calcolo oppure apportare modifiche alle impostazioni e alle preferenze.

Nota

Le soluzioni qui presentate sono specifiche per MATLAB. Per ottimizzare le prestazioni della memoria a livello di sistema, valutare la possibilità di aggiungere altra memoria fisica (RAM) al computer o di apportare modifiche a livello di sistema operativo.

Eliminazione delle variabili quando non sono più necessarie

È buona norma eliminare le variabili quando non sono più necessarie. Per eliminare degli elementi dalla memoria, utilizzare la funzione clear.

PrimaDopo
A = rand(1e4);
disp(max(A,[],"all"))
B = rand(1e4);
A = rand(1e4);
disp(max(A,[],"all"))
clear A
B = rand(1e4);

Per maggiori informazioni, vedere Strategies for Efficient Use of Memory.

Utilizzo di una memorizzazione appropriata dei dati

I requisiti di memoria variano a seconda dei tipi di dato di MATLAB. Potrebbe essere possibile ridurre la quantità di memoria utilizzata dal codice utilizzando il tipo di dato e lo spazio di archiviazione appropriati. Per maggiori informazioni sulle soluzioni illustrate in questa sezione, vedere Strategies for Efficient Use of Memory.

Utilizzo della classe numerica appropriata.  La classe numerica da utilizzare dipende dalle operazioni che si intende eseguire. In MATLAB, double è il tipo di dato numerico predefinito e fornisce una precisione sufficiente per la maggior parte delle attività di calcolo:

  • Se si desidera eseguire calcoli matematici complessi, come l'algebra lineare, utilizzare numeri in virgola mobile nel formato a doppia precisione (double) o a singola precisione (single). I numeri di tipo single richiedono meno memoria rispetto a quelli di tipo double, ma sono rappresentati con una precisione inferiore.

  • Se occorre eseguire solo semplici operazioni aritmetiche e i dati originali sono rappresentati come numeri interi, utilizzare le classi di numeri interi in MATLAB.

Classe (tipo di dato)ByteOperazioni supportate
single4La maggior parte della matematica
double8Tutta la matematica
logical1Operazioni logiche/condizionali
int8, uint81Aritmetica e alcune funzioni semplici
int16, uint162Aritmetica e alcune funzioni semplici
int32, uint324Aritmetica e alcune funzioni semplici
int64, uint648Aritmetica e alcune funzioni semplici

Riduzione del sovraccarico legato alla memorizzazione dei dati.  Quando si crea un array numerico o di caratteri, MATLAB alloca un blocco di memoria per memorizzare i dati dell'array. MATLAB memorizza inoltre le informazioni relative ai dati dell'array, quali la classe e le dimensioni, in un piccolo blocco di memoria separato denominato intestazione. Poiché gli array numerici e di caratteri semplici comportano il minor sovraccarico, utilizzarli ogni volta che è possibile. Utilizzare altre strutture di dati solo per dati troppo complessi per essere memorizzati in un array semplice.

Per le strutture e gli array di celle, MATLAB crea un'intestazione non solo per l'array, ma anche per ciascun campo della struttura o per ciascuna cella dell'array di celle. Pertanto, la quantità di memoria necessaria per memorizzare una struttura o un array di celle dipende non solo dalla quantità di dati che contiene, ma anche dal modo in cui è costruita. Di conseguenza, gli array di celle con molti elementi di piccole dimensioni o le strutture con molti campi contenenti pochi dati comportano un notevole sovraccarico e dovrebbero essere evitati.

PrimaDopo
% S has 15,000 fields (3 fields per array element)
for i = 1:100
    for j = 1:50
        S(i,j).R = 0;  % Each field contains a numeric scalar
        S(i,j).G = 0;
        S(i,j).B = 0;
    end
end
% S has 3 fields 
S.R = zeros(100,50);  % Each field contains a numeric array
S.G = zeros(100,50);
S.B = zeros(100,50);

Conversione in array sparsi quando possibile.  Una buona pratica consiste nel memorizzare le matrici con pochi elementi diversi da zero utilizzando la memorizzazione sparsa. Quando una matrice piena contiene un numero ridotto di elementi diversi da zero, la conversione della matrice in un formato sparso migliora in genere l'utilizzo della memoria e il tempo di esecuzione del codice. MATLAB dispone di diverse funzioni che supportano la memorizzazione sparsa. Ad esempio, è possibile utilizzare la funzione speye per creare una matrice di identità sparsa.

PrimaDopo
I = eye(1000);
I = speye(1000);

Importazione dei dati utilizzando la classe MATLAB appropriata.  Quando si leggono i dati da un file binario con fread, un errore comune consiste nello specificare solo la classe dei dati nel file e non la classe dei dati che MATLAB utilizza una volta che si trovano nel workspace. Se non si specifica la classe dei dati in memoria, MATLAB utilizza double anche se si leggono valori a 8 bit.

PrimaDopo
fileID = fopen("large_file_of_uint8s.bin","r"); 
A = fread(fileID,1e3,"uint8"); 
fileID = fopen("large_file_of_uint8s.bin","r"); 
A = fread(fileID,1e3,"uint8=>uint8"); 

Prevenzione di copie di dati non necessarie

Per migliorare l'utilizzo della memoria e la velocità di esecuzione, assicurarsi che il codice non generi copie di dati non necessarie. Per maggiori informazioni sulle soluzioni illustrate in questa sezione, vedere Avoid Unnecessary Copies of Data e Strategies for Efficient Use of Memory.

Prevenzione della creazione di array temporanei.  Evitare di creare array temporanei quando non sono necessari. Ad esempio, anziché creare un array di zeri come variabile temporanea e poi passare tale variabile a una funzione, utilizzare un unico comando per eseguire entrambe le operazioni.

PrimaDopo
A = zeros(1e6,1);
As = single(A);
As = zeros(1e6,1,"single");

Pre-allocazione della memoria.  Quando si lavora con grandi insiemi di dati, il ripetuto ridimensionamento degli array potrebbe causare l'esaurimento della memoria del programma. Se si espande un array oltre la memoria contigua disponibile nella sua posizione originale, MATLAB deve creare una copia dell'array e spostare la copia in un blocco di memoria con spazio sufficiente. Durante questo processo, in memoria sono presenti due copie dell'array originale. È possibile migliorare l'utilizzo della memoria e ridurre il tempo di esecuzione del codice pre-allocando la quantità massima di spazio necessaria per l'array. Per maggiori informazioni, vedere Pre-allocazione.

PrimaDopo
x = 0;
for k = 2:1000000
   x(k) = x(k-1) + 5;
end
x = zeros(1,1000000);
for k = 2:1000000
   x(k) = x(k-1) + 5;
end

Utilizzo delle funzioni annidate per passare un numero minore di argomenti.  Quando si chiama una funzione, MATLAB in genere crea una copia temporanea della variabile nel workspace del chiamante, qualora la funzione ne modifichi il valore. MATLAB applica varie tecniche per evitare di creare copie non necessarie, ma non è sempre possibile evitare la creazione di una copia temporanea di una variabile di input.

Un modo per evitare la creazione di copie temporanee nelle chiamate alle funzioni è quello di utilizzare le funzioni annidate. Una funzione annidata condivide il workspace di tutte le funzioni esterne, quindi non è necessario passare una copia delle variabili nella chiamata alla funzione. Per maggiori informazioni, vedere Nested Functions.

Caricamento limitato alla quantità di dati necessaria

Un modo per risolvere i problemi relativi alla memoria consiste nell'importare in MATLAB solo la quantità di dati necessaria di un insieme di dati di grandi dimensioni per il problema che si sta cercando di risolvere. La dimensione dell'insieme di dati non rappresenta solitamente un problema quando si esegue l'importazione da sorgenti quali un database, dove è possibile cercare esplicitamente gli elementi che corrispondono a una query. Si tratta però di un problema comune che si verifica quando si caricano file di testo semplici o file binari di grandi dimensioni.

La funzione datastore consente di lavorare in modo incrementale con insiemi di dati di grandi dimensioni. I datastore sono utili ogni volta che si desidera caricare in memoria solo alcune parti di un insieme di dati alla volta.

Per creare un datastore, fornire il nome di un file o di una cartella contenente una raccolta di file con una formattazione simile. Ad esempio, se si tratta di un singolo file, utilizzare quanto segue.

ds = datastore("path/to/file.csv");
Oppure, se si tratta di una raccolta di file contenuti in una cartella, utilizzare quanto segue.
ds = datastore("path/to/folder/");
È inoltre possibile utilizzare il carattere jolly * per selezionare tutti i file di un tipo specifico.
ds = datastore("path/to/*.csv");
I datastore supportano un'ampia varietà di formati di file (dati tabellari, immagini, fogli di calcolo e così via). Per maggiori informazioni, vedere Select Datastore for File Format or Application.

Oltre ai datastore, MATLAB dispone inoltre di diverse altre funzioni per caricare parti di file. Questa tabella riepiloga le funzioni in base al tipo di file su cui operano.

Tipo di fileCaricamento parziale
File MAT

Carica una parte di una variabile tramite indicizzazione a un oggetto creato con la funzione matfile. Per maggiori informazioni, vedere Save and Load Parts of Variables in MAT Files.

Testo

Utilizza la funzione textscan per accedere a parti di un file di testo di grandi dimensioni, leggendo solo le colonne e le righe selezionate. Se si specifica il numero di righe o un numero di formato di ripetizione con textscan, MATLAB calcola in anticipo la quantità esatta di memoria necessaria.

Binario

È possibile utilizzare funzioni di I/O di file binari di basso livello, come fread, per accedere a parti di qualsiasi file di cui si conosca il formato. Per i file binari di formato sconosciuto, provare a utilizzare la mappatura della memoria con la funzione memmapfile.

Immagini, audio, video e HDF

Molte delle funzioni di MATLAB che supportano il caricamento da questi tipi di file consentono di selezionare porzioni di dati da leggere. Per i dettagli, vedere le pagine di riferimento delle funzioni elencate in Supported File Formats for Import and Export.

Utilizzo dei tall array

I tall array consentono di lavorare con insiemi di dati troppo grandi per essere contenuti nella memoria. MATLAB funziona con piccoli blocchi di dati alla volta, gestendo automaticamente la scomposizione e l'elaborazione di tutti i dati in background. È possibile utilizzare i tall array in due modi principali:

  • Se si dispone di un array di grandi dimensioni che può essere contenuto in memoria, ma si esaurisce la memoria quando si tenta di eseguire calcoli, è possibile convertire l'array in un tall array.

    t = tall(A);
    Questo approccio consente di lavorare con array di grandi dimensioni che possono essere contenuti in memoria, ma che occupano troppa memoria per consentire la creazione di copie dei dati durante i calcoli. Ad esempio, se si dispone di 8 GB di RAM e di una matrice da 5 GB, la conversione della matrice in un tall array consente di eseguire i calcoli sulla matrice senza esaurire la memoria. Per un esempio di questo utilizzo, vedere tall.

  • Se si dispone di dati basati su file o cartelle, è possibile creare un datastore e quindi creare un tall array a partire dal datastore.

    ds = datastore("path/to/file.csv");
    t = tall(ds);
    Questo approccio consente di sfruttare appieno le potenzialità dei tall array in MATLAB. I dati possono contenere un numero qualsiasi di righe e MATLAB non esaurisce la memoria. Inoltre, poiché datastore funziona sia con posizioni di dati locali che remote, non è necessario che i dati su cui si lavora si trovino sul computer utilizzato per analizzarli. Per maggiori informazioni vedere Work with Remote Data.

Per saperne di più sui tall array, vedere Tall Arrays for Out-of-Memory Data.

Utilizzo della memoria di più macchine

Se si dispone di un cluster di computer, è possibile utilizzare gli array distribuiti (richiede Parallel Computing Toolbox™) per eseguire calcoli utilizzando la memoria combinata di tutte le macchine del cluster. A seconda di come i dati possono essere contenuti in memoria, esistono diversi modi per ripartire i dati tra i worker di un pool parallelo. Per maggiori informazioni, vedere Distributing Arrays to Parallel Workers (Parallel Computing Toolbox).

Modifica delle impostazioni e delle preferenze

In generale, la riscrittura del codice è il modo più efficace per migliorare le prestazioni della memoria. Tuttavia, se non è possibile apportare modifiche al codice, queste soluzioni potrebbero fornire al codice la quantità di memoria necessaria.

Avvio di MATLAB senza Java Virtual Machine o riduzione delle dimensioni dell'heap Java.  Se si avvia MATLAB senza il software Java® Virtual Machine (JVM®) oppure si riduce la dimensione dell'heap Java, è possibile aumentare la memoria disponibile per il workspace. Per avviare MATLAB senza JVM, utilizzare l'opzione dalla riga di comando -nojvm. Per informazioni su come ridurre la dimensione dell'heap Java, vedere Java Runtime Environment Settings.

L'utilizzo di -nojvm comporta uno svantaggio, ovvero la perdita di diverse feature che dipendono da JVM, come gli strumenti per il desktop e la grafica. L'avvio di MATLAB con l'opzione -nodesktop non comporta un risparmio significativo di memoria.

Modifica del limite delle dimensioni dell'array.  Se viene visualizzato un errore che indica che la dimensione dell'array supera il limite massimo impostato nelle preferenze, è possibile modificare tale limite in MATLAB. Per informazioni su come modificare il limite delle dimensioni dell'array, vedere Modify Workspace and Variables Settings. Questa soluzione è utile solo se l'array che si desidera creare supera l'attuale limite massimo per le dimensioni degli array, ma non è di dimensioni eccessive per essere contenuto in memoria. Anche se si disattiva il limite di dimensione dell'array, il tentativo di creare un array di dimensioni irragionevolmente grandi potrebbe causare l'esaurimento della memoria di MATLAB oppure impedire a MATLAB, o persino al computer, di rispondere a causa di un'eccessiva paginazione della memoria.

Vedi anche

| | |

Argomenti