Kesalahan: Penggunaan tumpukan C terlalu dekat dengan batas

88

Saya mencoba menjalankan beberapa kode rekursif yang cukup dalam di R dan itu terus memberi saya kesalahan ini:

Kesalahan: Penggunaan tumpukan C terlalu dekat dengan batas

Keluaran saya dari CStack_info()adalah:

Cstack_info()
    size    current  direction eval_depth 
67108864       8120          1          2 

Saya memiliki banyak memori di komputer saya, saya hanya mencoba mencari cara untuk meningkatkan CStack untuk R.

EDIT: Seseorang meminta contoh yang dapat direproduksi. Berikut beberapa kode contoh dasar yang menyebabkan masalah. Menjalankan f (1,1) beberapa kali Anda akan mendapatkan error. Perhatikan bahwa saya sudah menyetel --max-ppsize = 500000 dan opsi (ekspresi = 500000) jadi jika Anda tidak menyetelnya, Anda mungkin mendapatkan kesalahan tentang salah satu dari dua hal itu. Seperti yang Anda lihat, rekursi bisa sangat dalam di sini dan saya tidak tahu bagaimana membuatnya bekerja secara konsisten. Terima kasih.

f <- function(root=1,lambda=1) {
    x <- c(0,1);
    prob <- c(1/(lambda+1),lambda/(lambda+1));
        repeat {
      if(root == 0) {
        break;
      }
      else {
        child <- sample(x,2,replace=TRUE,prob);
        if(child[1] == 0 && child[2] == 0) {
          break;
        }
        if(child[1] == 1) {
          child[1] <- f(root=child[1],lambda);
        }
        if(child[2] == 1 && child[1] == 0) {
          child[2] <- f(root=child[2],lambda);
        }
      }
      if(child[1] == 0 && child[2] == 0) {
        break;
      }
      if(child[1] == 1 || child[2] == 1) {
        root <- sample(x,1,replace=TRUE,prob);
      }
        }
    return(root)
}
pengguna2045093
sumber
1
Pertanyaan ini mungkin menyarankanoptions(expressions = somethinglarge)
mnel
@mnel Kedalaman bersarang ekspresi, tumpukan perlindungan penunjuk, dan tumpukan C adalah tiga hal yang terpisah (tetapi terkait).
zwol
Terima kasih banyak atas tanggapan cepat Anda, Zack. Saya pikir jawaban Anda mungkin untuk OS Linux? Saya saat ini menjalankan Windows 7 64 bit, apakah itu mengubah segalanya? Sekali lagi terima kasih atas bantuannya.
pengguna2045093
2
Googling pesan kesalahan menunjukkan bahwa di masa lalu ini biasanya merupakan kesalahan dalam kode pengguna, jadi Anda mungkin harus mengurangi masalah Anda menjadi contoh sederhana yang dapat direproduksi dan mempostingnya di sini.
Martin Morgan
2
Saya tidak yakin ada kesalahan dalam kode sama sekali. Ini hanyalah kasus probabilitas yang secara teori dapat berakhir dengan rekursi tak terbatas. f (1,1) pada dasarnya adalah membalik koin. Itu bisa terus muncul selamanya. Untuk kondisi di mana tingkat rekursi tidak diketahui dan tidak terbatas, Anda lebih baik membuat sesuatu yang lebih berulang, menggunakan memoisasi hasil sample () sebelumnya untuk menginformasikan operasi di masa depan. Maka satu-satunya hal yang Anda ambil risiko adalah kehabisan memori vektor, atau disk, tergantung di mana Anda menyimpan backlog hasil. Rekursi bisa mahal dan rapuh.
Robert Casey

Jawaban:

57

Ukuran tumpukan adalah parameter sistem operasi, dapat disesuaikan per proses (lihat setrlimit(2)). Anda tidak dapat menyesuaikannya dari dalam R sejauh yang saya tahu, tetapi Anda dapat menyesuaikannya dari shell sebelum memulai R, dengan ulimitperintah. Ini bekerja seperti ini:

$ ulimit -s # print default
8192
$ R --slave -e 'Cstack_info()["size"]'
   size 
8388608

8388608 = 1024 * 8192; R mencetak nilai yang sama dengan ulimit -s, tetapi dalam byte, bukan kilobyte.

$ ulimit -s 16384 # enlarge stack limit to 16 megs
$ R --slave -e 'Cstack_info()["size"]'
    size 
16777216 

Untuk membuat penyesuaian permanen ke pengaturan ini, tambahkan ulimitperintah ke file startup shell Anda, sehingga dijalankan setiap kali Anda masuk. Saya tidak bisa memberikan petunjuk yang lebih spesifik dari itu, karena itu tergantung pada shell mana yang Anda miliki dan sebagainya. Saya juga tidak tahu bagaimana melakukannya untuk masuk ke lingkungan grafis (yang akan relevan jika Anda tidak menjalankan R di dalam jendela terminal).

zwol
sumber
12
... atau setel saja ke unlimited.
Paul Hiemstra
1
The RAppArmorpaket menawarkan sebuah antarmuka untuk setrlimit(2). Fungsionalitas ini mungkin tersedia dalam ulimitpaket di beberapa titik.
krlmlr
2
Fungsi ini tidak lagi ada di paket RAppArmor . Ada ide kemana perginya?
CoderGuy123
2
Apa perbaikan untuk Windows?
S. Perera
2
Mengubah batas tidak akan menyelesaikan masalah ini. Fungsi rekursif hanya akan terus berjalan sampai batas yang lebih tinggi tercapai.
Tom Kelly
27

Saya curiga, terlepas dari batas tumpukan, Anda akan berakhir dengan rekursi yang terlalu dalam. Misalnya, dengan lambda = Inf, f (1) mengarah ke rekursi langsung, tanpa batas. Kedalaman rekursi tampaknya berjalan acak, dengan beberapa kemungkinan r untuk melangkah lebih dalam, 1 - r menyelesaikan rekursi saat ini. Pada saat Anda mencapai batas tumpukan, Anda telah membuat banyak langkah 'lebih dalam'. Ini menyiratkan bahwa r> 1/2, dan sebagian besar waktu Anda hanya akan terus berulang.

Juga, tampaknya hampir mungkin untuk mendapatkan solusi analitik atau setidaknya numerik bahkan dalam menghadapi rekursi tak terbatas. Seseorang dapat mendefinisikan p sebagai probabilitas bahwa f (1) == 1, menulis ekspresi implisit untuk status 'anak' setelah satu iterasi, dan menyamakannya dengan p, dan menyelesaikannya. p kemudian dapat digunakan sebagai peluang sukses dalam satu hasil imbang dari distribusi binomial.

Martin Morgan
sumber
1
di sini sebenarnya adalah jawaban yang benar tersembunyi - pastikan Anda tidak terlalu tenggelam dalam pengulangan ...
Kamil S Jaron
Dalam kasus saya, kesalahan ini disebabkan oleh sumber skrip R yang sama beberapa kali (yaitu dalam beberapa skrip R) dalam proyek saya.
Good Will
15

Kesalahan ini bukan karena memori, melainkan karena rekursi . Suatu fungsi memanggil dirinya sendiri. Untuk mengilustrasikan poin tersebut, berikut adalah contoh minimal dari 2 fungsi yang saling memanggil:

change_to_factor <- function(x){
  x <- change_to_character(x)
  as.factor(x)
} 

change_to_character <- function(x){
  x <- change_to_factor(x)
  as.character(x)
}

change_to_character("1")

Kesalahan: Penggunaan tumpukan C 7971600 terlalu dekat dengan batas

Fungsi akan terus memanggil satu sama lain secara rekursif dan secara teoritis tidak akan pernah selesai. Ini hanya pemeriksaan dalam sistem Anda yang mencegah hal ini terjadi tanpa batas dan menghabiskan semua sumber daya komputasi mesin Anda. Anda perlu mengubah fungsi untuk memastikan bahwa mereka tidak memanggil dirinya sendiri (atau satu sama lain) secara rekursif.

Tom Kelly
sumber
10

Ini terjadi pada saya karena alasan yang sama sekali berbeda. Saya tidak sengaja membuat string yang sangat panjang saat menggabungkan dua kolom:

output_table_subset = mutate(big_data_frame,
     combined_table = paste0(first_part, second_part, col = "_"))

dari pada

output_table_subset = mutate(big_data_frame,
     combined_table = paste0(first_part, second_part, sep = "_"))

Butuh waktu lama bagi saya untuk mengetahuinya karena saya tidak pernah mengira pasta yang menyebabkan masalah.

Alex Joseph
sumber
Sama di sini, tapi saya sedang meringkas. Aku sudah seperti ini: summarize( states = paste0(state,collapse=', ') ). Ketika saya harus memiliki dilakukan sesuatu seperti: summarize( states = paste0(sort(unique(state)),collapse=', ') ). Sasarannya adalah untuk mendapatkan daftar status unik yang dipisahkan koma yang tersedia untuk setiap subkelompok.
Richard DiSalvo
4

Saya mengalami masalah yang sama saat menerima kesalahan "penggunaan tumpukan C terlalu dekat dengan batas" (meskipun untuk aplikasi lain daripada yang dinyatakan oleh user2045093 di atas). Saya mencoba proposal zwol tetapi tidak berhasil.

Yang mengejutkan saya sendiri, saya dapat memecahkan masalah dengan menginstal versi terbaru R untuk OS X (saat ini: versi 3.2.3) serta versi terbaru R Studio untuk OS X (saat ini: 0.99.840), karena saya saya bekerja dengan R Studio.

Semoga ini bisa membantu Anda juga.

DAW
sumber
1
Saya beralih ke versi R yang lebih tinggi. Ini berfungsi sekali, tetapi kesalahan muncul kembali dan konsisten sekarang. Tolong!
murphy1310
2

Salah satu masalah di sini adalah Anda menelepon ke fdalam dirinya sendiri

plop <- function(a = 2){
  pouet <- sample(a)
  plop(pouet)
}
plop()
Erreur : évaluations trop profondément imbriquées : récursion infinie / options(expressions=) ?
Erreur pendant l'emballage (wrapup) : évaluations trop profondément imbriquées : récursion infinie / options(expressions=) ?
Colin FAY
sumber
1

Untuk informasi semua orang, saya tiba-tiba mengalami ini dengan R 3.6.1 di Windows 7 (64-bit). Itu tidak menjadi masalah sebelumnya, dan sekarang batas tumpukan tampaknya bermunculan di mana-mana, ketika saya mencoba untuk "menyimpan (.)" Data atau bahkan melakukan "save.image (.)". Ini seperti serialisasi yang menghilangkan tumpukan ini.

Saya serius mempertimbangkan untuk kembali ke 3.6.0. Tidak terjadi di sana.


sumber
1

Milik saya mungkin kasus yang lebih unik, tetapi dapat membantu beberapa orang yang memiliki masalah persis seperti ini:

Kasing saya sama sekali tidak ada hubungannya dengan penggunaan ruang, tetap R memberikan:
C stack usage is too close to the limit

Saya memiliki fungsi yang ditentukan yang merupakan peningkatan dari fungsi dasar:

saveRDS ()

Namun, secara tidak
sengaja, fungsi yang ditentukan ini dipanggil saveRDS()alih-alih safe_saveRDS().
Jadi, melewati definisi itu, ketika kode sampai ke baris yang benar-benar digunakan saveRDS(...)(yang memanggil versi dasar asli, bukan yang ditingkatkan), itu memberikan kesalahan di atas dan dihancurkan.

Jadi, jika Anda mendapatkan kesalahan itu saat memanggil beberapa fungsi penyimpanan, lihat apakah Anda tidak sengaja menjalankannya.

Tony
sumber
0

Seperti yang ditulis Martin Morgan ... Masalahnya adalah Anda terlalu jauh berada di dalam rekursi. Jika rekursi tidak menyatu sama sekali, Anda harus memecahnya sendiri. Saya harap kode ini akan berfungsi, karena belum diuji. Namun setidaknya poin harus jelas di sini.

f <- function(root=1,lambda=1,depth=1) {
 if(depth > 256){
  return(NA)
 }
 x <- c(0,1);
 prob <- c(1/(lambda+1),lambda/(lambda+1));
 repeat {
  if(root == 0) {
    break;
  } else {
   child <- sample(x,2,replace=TRUE,prob);
   if(child[1] == 0 && child[2] == 0) {
     break;
   }
   if(child[1] == 1) {
     child[1] <- f(root=child[1],lambda,depth+1);
   }
   if(child[2] == 1 && child[1] == 0) {
     child[2] <- f(root=child[2],lambda,depth+1);
   }
  }
  if(child[1] == NA | child[2] == NA){
   return NA;
  }
  if(child[1] == 0 && child[2] == 0) {
    break;
  }
  if(child[1] == 1 || child[2] == 1) {
    root <- sample(x,1,replace=TRUE,prob);
  }
 }
 return(root)
}
Kamil S Jaron
sumber
0

Cara lain untuk menyebabkan masalah yang sama:

library(debug)
mtrace(lapply)

Panggilan rekursif tidak begitu jelas di sini.

Quigi
sumber
0

Jika Anda menggunakan plot_ly, periksa kolom mana yang Anda lewati. Tampaknya untuk kolom POSIXdt / ct, Anda harus menggunakan as.character () sebelum meneruskan ke plotly atau Anda mendapatkan pengecualian ini!

Fred Johnson
sumber
0

Saya sering menyertakan source("path/to/file/thefile.R")baris komentar di bagian atas skrip R, misalnya thefile.R, jadi saya dapat dengan mudah menyalin-tempel ini ke terminal untuk menjalankannya. Saya mendapatkan kesalahan ini jika saya lupa mengomentari baris, karena menjalankan file menjalankan file, yang menjalankan file, yang menjalankan file, ...

Jika itu penyebabnya, solusinya sederhana: beri komentar.

bstock
sumber
0

Tidak yakin apakah kami mencantumkan masalah di sini tetapi itu terjadi pada saya dengan leaflet(). Saya mencoba memetakan kerangka data yang datekolomnya berkelas POSIXlt. Mengubah kembali untuk POSIXctmemecahkan masalah.

YGS
sumber
0

Di Linux, saya telah secara permanen meningkatkan ukuran tumpukan dan memlock memori dengan melakukannya:

sudo vi /etc/security/limits.conf 

Kemudian, tambahkan baris berikut di akhir file.

* soft memlock unlimited
* hard memlock unlimited

* soft stack unlimited
* hard stack unlimited
Loulou
sumber