Mam naprawdę duży plik csv, który otworzyłem w pandach w następujący sposób ....
import pandas
df = pandas.read_csv('large_txt_file.txt')
Gdy to zrobię, moje użycie pamięci wzrośnie o 2 GB, co jest oczekiwane, ponieważ ten plik zawiera miliony wierszy. Mój problem pojawia się, gdy muszę uwolnić tę pamięć. Pobiegłem ...
del df
Jednak moje użycie pamięci nie spadło. Czy to niewłaściwe podejście do zwolnienia pamięci używanej przez ramkę danych pandy? Jeśli tak, jaki jest właściwy sposób?
gc
moduł i zadzwonićgc.collect()
, ale nie może odzyskać pamięćdel df
nie jest wywoływana bezpośrednio po utworzeniu df, prawda? Myślę, że w miejscu usunięcia pliku df są odniesienia do pliku df. Więc nie zostanie usunięty, zamiast tego usuwa nazwę.df = ''
na końcu twojego kodu? Wygląda na to, że ramka danych wyczyściła pamięć RAM.Odpowiedzi:
Zmniejszenie zużycia pamięci w Pythonie jest trudne, ponieważ Python w rzeczywistości nie zwalnia pamięci z powrotem do systemu operacyjnego . Jeśli usuniesz obiekty, pamięć będzie dostępna dla nowych obiektów Pythona, ale nie
free()
wróci do systemu ( zobacz to pytanie ).Jeśli trzymasz się numerycznych tablic numpy, są one uwalniane, ale obiekty w pudełkach nie.
Zmniejszanie liczby ramek danych
Python utrzymuje naszą pamięć na wysokim znaku wodnym, ale możemy zmniejszyć całkowitą liczbę tworzonych ramek danych. Podczas modyfikowania ramki danych preferuj
inplace=True
, aby nie tworzyć kopii.Innym częstym problemem jest zatrzymywanie kopii wcześniej utworzonych ramek danych w ipythonie:
Możesz to naprawić, wpisując,
%reset Out
aby wyczyścić historię. Alternatywnie możesz dostosować, ile historii przechowuje ipythonipython --cache-size=5
(domyślnie jest to 1000).Zmniejszanie rozmiaru ramki danych
Jeśli to możliwe, unikaj używania dtypów obiektów.
Wartości z typem obiektu są opakowane w ramkę, co oznacza, że tablica numpy zawiera po prostu wskaźnik i masz pełny obiekt Pythona na stercie dla każdej wartości w ramce danych. Obejmuje to ciągi.
Podczas gdy numpy obsługuje ciągi o stałym rozmiarze w tablicach, pandy nie ( powoduje to zamieszanie użytkownika ). Może to mieć istotne znaczenie:
Możesz uniknąć używania kolumn łańcuchowych lub znaleźć sposób na przedstawienie danych w postaci ciągów jako liczb.
Jeśli masz ramkę danych, która zawiera wiele powtarzających się wartości (NaN jest bardzo powszechne), możesz użyć rzadkiej struktury danych, aby zmniejszyć zużycie pamięci:
Przeglądanie wykorzystania pamięci
Możesz wyświetlić użycie pamięci ( dokumenty ):
Począwszy od pandy 0.17.1, możesz również
df.info(memory_usage='deep')
zobaczyć użycie pamięci, w tym obiekty.źródło
Jak zauważono w komentarzach, jest kilka rzeczy do wypróbowania:
gc.collect
(@EdChum) może na przykład wyczyścić rzeczy. Przynajmniej z mojego doświadczenia, te rzeczy czasami działają, a często nie.Jest jednak jedna rzecz, która zawsze działa, ponieważ jest wykonywana na poziomie systemu operacyjnego, a nie języka.
Załóżmy, że masz funkcję, która tworzy pośrednią ogromną ramkę DataFrame i zwraca mniejszy wynik (którym może być również DataFrame):
Wtedy jeśli zrobisz coś takiego
Następnie funkcja jest wykonywana w innym procesie . Po zakończeniu tego procesu system operacyjny ponownie pobiera wszystkie wykorzystane zasoby. Naprawdę nie ma nic, co mógłby zrobić Python, pandy i śmieciarki, aby to powstrzymać.
źródło
with multiprocessing.Pool(1) as pool: result = pool.map(huge_intermediate_calc, [something])
co oznacza zamknięcie puli po zakończeniu.To rozwiązuje problem zwolnienia pamięci dla mnie !!!
ramka danych zostanie jawnie ustawiona na wartość null
źródło
del df
nie zostanie usunięty, jeśli istnieją jakiekolwiek odniesienia dodf
czasu usunięcia. Musisz więc usunąć wszystkie odniesienia do niego za pomocą,del df
aby zwolnić pamięć.Dlatego wszystkie wystąpienia powiązane z df powinny zostać usunięte, aby wyzwolić czyszczenie pamięci.
Użyj objgragh, aby sprawdzić, który trzyma obiekty.
źródło
Wygląda na to, że istnieje problem z glibc, który wpływa na alokację pamięci w Pandach: https://github.com/pandas-dev/pandas/issues/2659
Łata małpa wyszczególnione w tej sprawie został rozwiązany problem dla mnie:
źródło