Trik apa yang digunakan orang untuk mengelola memori sesi R interaktif yang tersedia? Saya menggunakan fungsi-fungsi di bawah ini [berdasarkan pada posting oleh Petr Pikal dan David Hinds ke daftar r-help pada 2004] untuk membuat daftar (dan / atau mengurutkan) objek terbesar dan kadang-kadang rm()
beberapa di antaranya. Tetapi sejauh ini solusi yang paling efektif adalah ... berjalan di bawah Linux 64-bit dengan memori yang cukup.
Adakah trik bagus lain yang ingin dibagikan orang? Tolong satu per posting.
# improved list of objects
.ls.objects <- function (pos = 1, pattern, order.by,
decreasing=FALSE, head=FALSE, n=5) {
napply <- function(names, fn) sapply(names, function(x)
fn(get(x, pos = pos)))
names <- ls(pos = pos, pattern = pattern)
obj.class <- napply(names, function(x) as.character(class(x))[1])
obj.mode <- napply(names, mode)
obj.type <- ifelse(is.na(obj.class), obj.mode, obj.class)
obj.size <- napply(names, object.size)
obj.dim <- t(napply(names, function(x)
as.numeric(dim(x))[1:2]))
vec <- is.na(obj.dim)[, 1] & (obj.type != "function")
obj.dim[vec, 1] <- napply(names, length)[vec]
out <- data.frame(obj.type, obj.size, obj.dim)
names(out) <- c("Type", "Size", "Rows", "Columns")
if (!missing(order.by))
out <- out[order(out[[order.by]], decreasing=decreasing), ]
if (head)
out <- head(out, n)
out
}
# shorthand
lsos <- function(..., n=10) {
.ls.objects(..., order.by="Size", decreasing=TRUE, head=TRUE, n=n)
}
memory-management
r
Dirk Eddelbuettel
sumber
sumber
multilevelPSA
paket . Paket ini dirancang untuk sesuatu yang lain, tetapi Anda dapat menggunakan fungsi dari sana tanpa memuat paket dengan mengatakanrequireNamespace(multilevelPSA); multilevelPSA::lsos(...)
. Atau dalamDmisc
paket (bukan pada CRAN).Jawaban:
Pastikan Anda merekam pekerjaan Anda dalam skrip yang dapat direproduksi. Dari waktu ke waktu, buka kembali R, lalu
source()
skrip Anda. Anda akan membersihkan apa pun yang tidak lagi Anda gunakan, dan sebagai manfaat tambahan akan menguji kode Anda.sumber
1-load.r
,2-explore.r
,3-model.r
- dengan cara itu jelas kepada orang lain bahwa ada beberapa urutan hadir.Saya menggunakan paket data.table . Dengan
:=
operatornya Anda dapat:Tak satu pun dari operasi ini menyalin (berpotensi besar)
data.table
sama sekali, bahkan tidak sekali.data.table
menggunakan memori yang bekerja jauh lebih sedikit.Tautan yang berhubungan :
:=
operator dalam data.table?sumber
Lihat ini di posting twitter dan anggap ini fungsi luar biasa dari Dirk! Sebagai lanjutan dari jawaban JD Long, saya akan melakukan ini untuk membaca ramah pengguna:
Yang menghasilkan sesuatu seperti berikut:
CATATAN: Bagian utama yang saya tambahkan adalah (sekali lagi, diadaptasi dari jawaban JD):
sumber
capture.output
tidak perlu lagi, danobj.prettysize <- napply(names, function(x) {format(utils::object.size(x), units = "auto") })
menghasilkan keluaran bersih. Bahkan, tidak menghapusnya menghasilkan kutipan yang tidak diinginkan di output, yaitu[1] "792.5 Mb"
bukannya792.5 Mb
.obj.class <- napply(names, function(x) as.character(class(x))[1])
menjadiobj.class <- napply(names, function(x) class(x)[1])
karenaclass
selalu mengembalikan vektor karakter sekarang (base-3.5.0).Saya menggunakan
subset
parameter secara agresif dengan hanya memilih variabel yang diperlukan ketika meneruskan kerangka data kedata=
argumen fungsi regresi. Itu memang menghasilkan beberapa kesalahan jika saya lupa menambahkan variabel ke rumus danselect=
vektor, tetapi masih menghemat banyak waktu karena penurunan penyalinan objek dan mengurangi jejak memori secara signifikan. Katakanlah saya memiliki 4 juta catatan dengan 110 variabel (dan saya punya.) Contoh:Dengan cara menetapkan konteks dan strategi:
gdlab2
variabel adalah vektor logis yang dibangun untuk subjek dalam dataset yang memiliki semua nilai normal atau hampir normal untuk sekelompok tes laboratorium danHIVfinal
merupakan vektor karakter yang merangkum tes pendahuluan dan konfirmasi untuk HIV .sumber
Saya suka skrip .ls.objects () dari Dirk, tetapi saya tetap menyipitkan mata untuk menghitung karakter di kolom ukuran. Jadi saya melakukan beberapa hacks jelek untuk membuatnya hadir dengan format yang cukup untuk ukuran:
sumber
Itu trik yang bagus.
Satu saran lain adalah untuk menggunakan objek yang efisien memori sedapat mungkin: misalnya, gunakan matriks, bukan data.frame.
Ini tidak benar-benar menangani manajemen memori, tetapi satu fungsi penting yang tidak banyak dikenal adalah memory.limit (). Anda dapat meningkatkan default menggunakan perintah ini, memory.limit (size = 2500), di mana ukurannya dalam MB. Seperti yang disebutkan Dirk, Anda harus menggunakan 64-bit untuk mengambil keuntungan nyata dari ini.
sumber
Saya sangat menyukai fungsi objek yang dikembangkan oleh Dirk. Namun, sebagian besar waktu, keluaran yang lebih mendasar dengan nama dan ukuran objek cukup bagi saya. Inilah fungsi yang lebih sederhana dengan tujuan yang serupa. Penggunaan memori dapat dipesan berdasarkan abjad atau berdasarkan ukuran, dapat dibatasi untuk sejumlah objek tertentu, dan dapat dipesan naik atau turun. Juga, saya sering bekerja dengan data yang 1GB +, jadi fungsinya berubah satuan.
Dan inilah beberapa contoh output:
sumber
Saya tidak pernah menyimpan ruang kerja R. Saya menggunakan skrip impor dan skrip data dan menampilkan objek data besar apa pun yang tidak ingin sering saya buat ulang ke file. Dengan cara ini saya selalu memulai dengan ruang kerja baru dan tidak perlu membersihkan benda besar. Itu adalah fungsi yang sangat bagus.
sumber
Sayangnya saya tidak punya waktu untuk mengujinya secara ekstensif tetapi di sini ada tip memori yang belum pernah saya lihat sebelumnya. Bagi saya memori yang dibutuhkan berkurang dengan lebih dari 50%. Ketika Anda membaca barang-barang ke R dengan misalnya read.csv mereka memerlukan sejumlah memori. Setelah ini, Anda dapat menyimpannya dengan
save("Destinationfile",list=ls())
lain kali Anda membuka R Anda dapat menggunakanload("Destinationfile")
Sekarang penggunaan memori mungkin telah menurun. Alangkah baiknya jika ada yang bisa mengkonfirmasi apakah ini menghasilkan hasil yang sama dengan dataset yang berbeda.sumber
fread
, kemudian disimpan ke. Data. File RData memang sekitar 70% lebih kecil tetapi setelah memuat ulang, memori yang digunakan persis sama. Berharap trik ini akan mengurangi jejak memori ... apakah saya melewatkan sesuatu?Untuk mengilustrasikan strategi umum restart yang sering, kita dapat menggunakan littler yang memungkinkan kita untuk menjalankan ekspresi sederhana langsung dari baris perintah. Berikut adalah contoh yang kadang saya gunakan untuk menentukan waktu BLAS berbeda untuk crossprod sederhana.
Juga,
memuat paket Matrix (melalui saklar --packages | -l) dan menjalankan contoh fungsi spMatrix. Karena r selalu memulai 'fresh', metode ini juga merupakan tes yang baik selama pengembangan paket.
Last but not least r juga berfungsi baik untuk mode batch otomatis dalam skrip menggunakan shebang-header '#! / Usr / bin / r'. Rscript adalah alternatif di mana littler tidak tersedia (misalnya pada Windows).
sumber
Untuk keperluan kecepatan dan memori, saat membangun bingkai data besar melalui serangkaian langkah yang kompleks, saya akan secara berkala menyiramnya (set data yang sedang dibuat sedang dibangun) ke disk, menambahkan ke apa pun yang datang sebelumnya, dan kemudian memulai kembali. . Dengan cara ini langkah-langkah perantara hanya bekerja pada frame data bertubuh kecil (yang bagus, misalnya, rbind melambat jauh dengan objek yang lebih besar). Seluruh kumpulan data dapat dibaca kembali di akhir proses, ketika semua objek perantara telah dihapus.
sumber
Hanya untuk dicatat bahwa
data.table
pakettables()
tampaknya merupakan pengganti yang cukup bagus untuk.ls.objects()
fungsi kustom Dirk (dirinci dalam jawaban sebelumnya), meskipun hanya untuk data.frame / tabel dan bukan misalnya matriks, array, daftar.sumber
Saya beruntung dan set data saya yang besar disimpan oleh instrumen dalam "potongan" (himpunan bagian) sekitar 100 MB (biner 32bit). Jadi saya dapat melakukan langkah-langkah pra-pemrosesan (menghapus bagian yang tidak informatif, downsampling) secara berurutan sebelum menggabungkan set data.
Memanggil
gc ()
"dengan tangan" dapat membantu jika ukuran data mendekati memori yang tersedia.Terkadang algoritma yang berbeda membutuhkan lebih sedikit memori.
Terkadang ada trade off antara vektorisasi dan penggunaan memori.
bandingkan:
split
&lapply
vs. satufor
loop.Demi analisis data yang cepat & mudah, saya sering bekerja dulu dengan subset acak kecil (
sample ()
) dari data. Setelah script analisis data / .Rnw selesai kode analisis data dan data lengkap pergi ke server perhitungan untuk perhitungan malam / akhir pekan / ...sumber
Penggunaan lingkungan alih-alih daftar untuk menangani koleksi objek yang menempati sejumlah besar memori yang bekerja.
Alasannya: setiap kali elemen
list
struktur diubah, seluruh daftar sementara digandakan. Ini menjadi masalah jika persyaratan penyimpanan daftar adalah sekitar setengah dari memori yang tersedia, karena data harus ditukar dengan hard disk yang lambat. Lingkungan, di sisi lain, tidak tunduk pada perilaku ini dan mereka dapat diperlakukan serupa dengan daftar.Berikut ini sebuah contoh:
Dalam hubungannya dengan struktur seperti
big.matrix
ataudata.table
yang memungkinkan untuk mengubah konten mereka di tempat, penggunaan memori yang sangat efisien dapat dicapai.sumber
The
ll
fungsi dalamgData
paket dapat menunjukkan penggunaan memori setiap objek juga.sumber
Jika Anda benar-benar ingin menghindari kebocoran, Anda harus menghindari membuat benda besar di lingkungan global.
Apa yang biasanya saya lakukan adalah memiliki fungsi yang melakukan pekerjaan dan mengembalikan
NULL
- semua data dibaca dan dimanipulasi dalam fungsi ini atau orang lain yang dipanggil.sumber
Dengan hanya 4GB RAM (menjalankan Windows 10, jadi buatlah sekitar 2 atau lebih 1GB realistis) Saya harus benar-benar berhati-hati dengan alokasi.
Saya menggunakan data.tabel hampir secara eksklusif.
Fungsi 'ketakutan' memungkinkan Anda untuk mengelompokkan informasi menurut nama bidang saat impor; hanya mengimpor bidang yang benar-benar diperlukan untuk memulai. Jika Anda menggunakan basis R baca, null kolom palsu segera setelah impor.
Sebagai 42- disarankan oleh , jika memungkinkan saya kemudian akan mengelompokkan dalam kolom segera setelah mengimpor informasi.
Saya sering rm () objek dari lingkungan segera setelah mereka tidak lagi diperlukan, misalnya pada baris berikutnya setelah menggunakannya untuk mengelompokkan sesuatu yang lain, dan memanggil gc ().
'fread' dan 'fwrite' dari data.table bisa sangat cepat dibandingkan dengan base R membaca dan menulis.
Sebagai kpierce8 disarankan oleh , saya hampir selalu menulis semuanya dari lingkungan dan membuatnya takut, bahkan dengan ribuan / ratusan ribu file kecil yang harus dilalui. Ini tidak hanya menjaga lingkungan tetap 'bersih' dan membuat alokasi memori rendah tetapi, mungkin karena kurangnya RAM yang tersedia, R memiliki kecenderungan untuk sering crash di komputer saya; sangat sering. Memiliki informasi yang dicadangkan di drive itu sendiri ketika kode berlangsung melalui berbagai tahapan berarti saya tidak harus mulai dari awal jika crash.
Pada 2017, saya pikir SSD tercepat berjalan sekitar beberapa GB per detik melalui port M2. Saya memiliki 50GB Kingston V300 (550MB / s) SSD yang benar-benar dasar yang saya gunakan sebagai disk utama saya (memiliki Windows dan R di atasnya). Saya menyimpan semua informasi massal di piring WD 500GB yang murah. Saya memindahkan set data ke SSD ketika saya mulai mengerjakannya. Ini, dikombinasikan dengan 'menakut-nakuti dan' menulis 'semuanya telah bekerja dengan baik. Saya sudah mencoba menggunakan 'ff' tetapi lebih suka yang pertama. Kecepatan baca / tulis 4K dapat menimbulkan masalah dengan ini; mencadangkan seperempat juta file 1k (senilai 250MB) dari SSD ke piring dapat berlangsung berjam-jam. Sejauh yang saya ketahui, belum ada paket R yang tersedia yang dapat secara otomatis mengoptimalkan proses 'chunkification'; mis. lihat berapa banyak RAM yang dimiliki pengguna, uji kecepatan baca / tulis RAM / semua drive yang terhubung dan kemudian sarankan protokol 'chunkification' yang optimal. Ini dapat menghasilkan beberapa peningkatan alur kerja yang signifikan / optimisasi sumber daya; misalnya membaginya menjadi ... MB untuk ram -> membaginya menjadi ... MB untuk SSD -> membaginya menjadi ... MB di piring -> membaginya menjadi ... MB pada kaset. Ini bisa mengambil sampel set data sebelumnya untuk memberikan tongkat pengukur yang lebih realistis untuk bekerja.
Banyak masalah yang saya kerjakan di R melibatkan pembentukan kombinasi dan permutasi pasangan, tiga kali lipat dll, yang hanya membuat memiliki keterbatasan RAM lebih dari batasan karena mereka akan setidaknya setidaknya secara eksponensial berkembang di beberapa titik. Ini telah membuat saya memusatkan banyak perhatian pada kualitas daripada kuantitas informasi yang masuk ke mereka untuk memulai, daripada mencoba untuk membersihkannya setelah itu, dan pada urutan operasi dalam menyiapkan informasi untuk memulai (dimulai dengan operasi paling sederhana dan menambah kompleksitas); misal subset, lalu gabung / gabung, lalu bentuk kombinasi / permutasi dll.
Tampaknya ada beberapa manfaat untuk menggunakan basis R membaca dan menulis dalam beberapa kasus. Misalnya, deteksi kesalahan dalam 'fread' sangat bagus sehingga sulit untuk mencoba mendapatkan informasi yang benar-benar berantakan ke R untuk memulai dengan membersihkannya. Basis R juga tampaknya jauh lebih mudah jika Anda menggunakan Linux. Basis R tampaknya berfungsi dengan baik di Linux, Windows 10 menggunakan ~ 20GB ruang disk sedangkan Ubuntu hanya membutuhkan beberapa GB, RAM yang dibutuhkan dengan Ubuntu sedikit lebih rendah. Tetapi saya telah memperhatikan sejumlah besar peringatan dan kesalahan saat menginstal paket pihak ketiga di (L) Ubuntu. Saya tidak akan merekomendasikan melayang terlalu jauh dari (L) Ubuntu atau distribusi saham lainnya dengan Linux karena Anda dapat kehilangan begitu banyak kompatibilitas secara keseluruhan sehingga prosesnya hampir tidak ada gunanya (saya pikir 'unity' akan dibatalkan di Ubuntu pada 2017 ).
Semoga beberapa dari itu dapat membantu orang lain.
sumber
Ini tidak menambahkan apa pun di atas, tetapi ditulis dengan gaya sederhana dan sangat dikomentari yang saya sukai. Ini menghasilkan tabel dengan objek yang dipesan dalam ukuran, tetapi tanpa beberapa detail yang diberikan dalam contoh di atas:
sumber
Ini adalah jawaban yang lebih baru untuk pertanyaan lama yang luar biasa ini. Dari Hadley's Advanced R:
( http://adv-r.had.co.nz/memory.html )
sumber
Jika Anda bekerja di Linux dan ingin menggunakan beberapa proses dan hanya perlu melakukan operasi baca pada satu atau lebih objek besar gunakan
makeForkCluster
sebagai ganti amakePSOCKcluster
. Ini juga menghemat waktu Anda mengirim objek besar ke proses lainnya.sumber
Saya benar-benar menghargai beberapa jawaban di atas, mengikuti @Hadley dan @Dirk yang menyarankan untuk menutup R dan mengeluarkan
source
dan menggunakan baris perintah saya datang dengan solusi yang bekerja sangat baik untuk saya. Saya harus berurusan dengan ratusan spektrum massa, masing-masing menempati sekitar 20 Mb memori jadi saya menggunakan dua skrip R, sebagai berikut:Pertama pembungkus:
dengan skrip ini saya pada dasarnya mengontrol apa yang dilakukan skrip utama saya
runConsensus.r
, dan saya menulis jawaban data untuk hasilnya. Dengan ini, setiap kali wrapper memanggil skrip, tampaknya R dibuka kembali dan memori dibebaskan.Semoga ini bisa membantu.
sumber
Selain teknik manajemen memori yang lebih umum yang diberikan dalam jawaban di atas, saya selalu berusaha mengurangi ukuran objek saya sejauh mungkin. Sebagai contoh, saya bekerja dengan matriks yang sangat besar tetapi sangat jarang, dengan kata lain matriks di mana sebagian besar nilai adalah nol. Menggunakan paket 'Matrix' (huruf besar penting), saya dapat mengurangi ukuran objek rata-rata dari ~ 2GB hingga ~ 200MB semudah:
Paket Matrix mencakup format data yang dapat digunakan persis seperti matriks biasa (tidak perlu mengubah kode Anda yang lain) tetapi mampu menyimpan data jarang jauh lebih efisien, apakah dimuat ke dalam memori atau disimpan ke disk.
Selain itu, file mentah yang saya terima dalam format 'panjang' di mana setiap titik data memiliki variabel
x, y, z, i
. Jauh lebih efisien untuk mengubah data menjadix * y * z
array dimensi dengan hanya variabeli
.Ketahui data Anda dan gunakan sedikit akal sehat.
sumber
Kiat untuk berurusan dengan objek yang membutuhkan perhitungan menengah yang berat: Saat menggunakan objek yang membutuhkan banyak perhitungan berat dan langkah-langkah perantara untuk membuat, saya sering merasa berguna untuk menulis sepotong kode dengan fungsi untuk membuat objek, dan kemudian potongan terpisah kode yang memberi saya pilihan untuk membuat dan menyimpan objek sebagai
rmd
file, atau memuatnya secara eksternal darirmd
file yang sudah saya simpan sebelumnya. Ini sangat mudah dilakukan dalamR Markdown
menggunakan struktur kode-chunk berikut.Dengan struktur kode ini, yang perlu saya lakukan adalah mengubah
LOAD
tergantung pada apakah saya ingin membuat dan menyimpan objek, atau memuatnya langsung dari file tersimpan yang ada. (Tentu saja, saya harus membuat dan menyimpannya untuk pertama kali, tetapi setelah ini saya memiliki pilihan untuk memuatnya.) PengaturanLOAD = TRUE
memotong penggunaan fungsi saya yang rumit dan menghindari semua perhitungan berat di dalamnya. Metode ini masih membutuhkan memori yang cukup untuk menyimpan objek yang menarik, tetapi ini menghemat Anda dari keharusan untuk menghitungnya setiap kali Anda menjalankan kode Anda. Untuk objek yang membutuhkan banyak perhitungan langkah menengah (mis., Untuk perhitungan yang melibatkan loop pada array besar) ini dapat menghemat banyak waktu dan perhitungan.sumber
Lari
dari waktu ke waktu juga membantu R untuk membebaskan memori yang tidak digunakan tetapi masih belum dirilis.
sumber
for
loop di sini? Tidak adai
dalamgc
panggilan.gc(reset = T)
sembilan kaliAnda juga bisa mendapatkan manfaat menggunakan rajutan dan meletakkan skrip Anda di rmd chuncks.
Saya biasanya membagi kode dalam potongan yang berbeda dan memilih mana yang akan menyimpan pos pemeriksaan ke cache atau ke file RDS, dan
Di sana Anda dapat mengatur chunk untuk disimpan ke "cache", atau Anda dapat memutuskan untuk menjalankan atau tidak chunk tertentu. Dengan cara ini, dalam menjalankan pertama Anda hanya dapat memproses "bagian 1", eksekusi lain Anda hanya dapat memilih "bagian 2", dll.
Contoh:
Sebagai efek samping, ini juga bisa menyelamatkan Anda dari sakit kepala dalam hal reproduksibilitas :)
sumber
Berdasarkan jawaban @ Dirk dan @ Tony, saya telah melakukan sedikit pembaruan. Hasilnya adalah keluaran
[1]
sebelum nilai ukuran cantik, jadi saya mengambilcapture.output
yang memecahkan masalah:sumber
Saya mencoba untuk menjaga jumlah objek kecil ketika bekerja di proyek yang lebih besar dengan banyak langkah perantara. Jadi alih-alih menciptakan banyak objek unik yang disebut
dataframe
->step1
->step2
->step3
->result
raster
->multipliedRast
->meanRastF
->sqrtRast
->resultRast
Saya bekerja dengan objek sementara yang saya panggil
temp
.dataframe
->temp
->temp
->temp
->result
Yang membuat saya dengan file kurang menengah dan lebih banyak ikhtisar.
Untuk menghemat lebih banyak memori, saya cukup menghapusnya
temp
saat tidak diperlukan lagi.Jika saya perlu beberapa file intermediate, saya menggunakan
temp1
,temp2
,temp3
.Untuk pengujian saya menggunakan
test
,test2
...sumber