Hata: C yığın kullanımı sınıra çok yakın


88

R'de oldukça derin özyinelemeli bir kod çalıştırmaya çalışıyorum ve bana şu hatayı vermeye devam ediyor:

Hata: C yığın kullanımı sınıra çok yakın

Benim çıktım CStack_info():

Cstack_info()
    size    current  direction eval_depth 
67108864       8120          1          2 

Makinemde bol miktarda bellek var, sadece R için CStack'i nasıl artırabileceğimi anlamaya çalışıyorum.

DÜZENLEME: Biri tekrarlanabilir bir örnek istedi. Soruna neden olan bazı temel örnek kodları burada bulabilirsiniz. F (1,1) 'i birkaç kez çalıştırdığınızda hatayı alırsınız. --Max-ppsize = 500000 ve seçenekleri (ifadeler = 500000) zaten belirlediğime dikkat edin, bu nedenle bunları ayarlamazsanız, bunun yerine bu iki şeyden biri hakkında bir hata alabilirsiniz. Gördüğünüz gibi, özyineleme burada oldukça derinlere inebilir ve bunu tutarlı bir şekilde nasıl çalıştıracağım konusunda hiçbir fikrim yok. Teşekkürler.

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)
}

1
Bu soru belki öneriyoroptions(expressions = somethinglarge)
mnel

@mnel İfade iç içe geçme derinliği, işaretçi koruma yığını ve C yığını üç ayrı (ancak ilişkili) şeydir.
zwol

Hızlı cevabın için çok teşekkürler, Zack. Sanırım cevabınız bir Linux işletim sistemi için olabilir mi? Şu anda Windows 7 64 bit çalıştırıyorum, bu herhangi bir şeyi değiştirir mi? Herhangi bir yardım için tekrar teşekkürler.
kullanıcı2045093

2
Hata mesajını araştırmak, geçmişte bunun genellikle kullanıcı kodunda bir hata olduğunu gösterir, bu nedenle probleminizi muhtemelen basit bir tekrarlanabilir örneğe indirip buraya göndermelisiniz.
Martin Morgan

2
Kodda bir hata olduğundan emin değilim. Bu sadece teoride sonsuz özyineleme ile sonuçlanabilecek bir olasılık durumudur. f (1,1) temelde bir yazı tura atmaktır. Sonsuza kadar kafa tutmaya devam edebilir. Yineleme seviyesinin bilinmediği ve sınırsız olduğu bir durumda, gelecekteki işlemleri bilgilendirmek için önceki sample () sonuçlarının hatırlanmasını kullanarak daha yinelemeli bir şey bulmanız daha iyidir. O zaman risk aldığınız tek şey, sonuç birikiminizi nerede depoladığınıza bağlı olarak vektör belleğinin veya diskin tükenmesidir. Özyineleme pahalı ve kırılgan olabilir.
Robert Casey

Yanıtlar:


57

Yığın boyutu, işlem başına ayarlanabilen bir işletim sistemi parametresidir (bkz. setrlimit(2)). Anladığım kadarıyla bunu R içinden ayarlayamazsınız, ancak ulimitkomutla R'yi başlatmadan önce kabuktan ayarlayabilirsiniz . Şu şekilde çalışır:

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

8388608 = 1024 * 8192; R, ulimit -skilobayt yerine bayt cinsinden, ile aynı değeri yazdırıyor .

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

Bu ayarda kalıcı bir ayarlama yapmak için, ulimitkomutu kabuk başlangıç ​​dosyanıza ekleyin , böylece her oturum açtığınızda yürütülür. Bundan daha spesifik talimatlar veremem, çünkü tam olarak hangi kabuğa sahip olduğunuza ve diğer şeylere bağlıdır. Ayrıca bir grafik ortamda oturum açmak için nasıl yapılacağını bilmiyorum (bu, R'yi bir terminal penceresinde çalıştırmıyorsanız ilgili olacaktır).


12
... veya sadece olarak ayarlayın unlimited.
Paul Hiemstra

1
RAppArmorPaket için bir arayüz sunar setrlimit(2). Bu işlevsellik bir ulimitnoktada pakette kullanılabilir hale gelebilir .
krlmlr

2
Bu işlev artık RAppArmor paketinde mevcut değildir. Nereye gittiğine dair bir fikrin var mı?
CoderGuy123

2
Windows için düzeltme nedir?
S.Perera

2
Limitin değiştirilmesi bunu çözmeyecektir. Özyinelemeli bir işlev, yüksek sınıra ulaşılana kadar çalışmaya devam edecektir.
Tom Kelly

27

Yığın sınırına bakılmaksızın, çok derin özyinelemelerle sonuçlanacağından şüpheleniyorum. Örneğin, lambda = Inf ile, f (1) sonsuza kadar ani özyinelemeye yol açar. Özyinelemenin derinliği rastgele bir yürüyüş gibi görünüyor, biraz daha derine inme olasılığı, 1 - r mevcut özyinelemeyi bitirme olasılığı. Yığın sınırına ulaştığınızda, çok sayıda adım 'derinleştirmişsinizdir'. Bu, r> 1/2 olduğu anlamına gelir ve çoğu zaman sadece tekrar etmeye devam edersiniz.

Ayrıca, sonsuz özyineleme karşısında bile analitik veya en azından sayısal bir çözüm elde etmek neredeyse mümkün gibi görünüyor. P, f (1) == 1, tek bir yinelemeden sonra 'çocuk' durumları için örtük ifadeler yazıp bunları p ile eşitleyip çözme olasılığı olarak tanımlanabilir. p, daha sonra iki terimli bir dağılımdan tek bir çekilişte başarı şansı olarak kullanılabilir.


1
Burada aslında doğru cevap gizlidir - makyaj emin recusion o derine alamadım ...
Kamil S Jaron

Benim durumumda, hata aynı R betiğinin projemde birden çok kez (yani birden çok R betiklerinde) kaynaklanmasından kaynaklanıyor.
İyi Niyet

15

Bu hata bellekten kaynaklanmamaktadır, özyinelemeden kaynaklanmaktadır . Bir işlev kendisini çağırıyor. Bu noktayı açıklamak için, işte birbirini çağıran 2 işlevin minimal bir örneği:

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")

Hata: 7971600 C yığın kullanımı sınıra çok yakın

İşlevler birbirini yinelemeli olarak çağırmaya devam edecek ve teorik olarak asla tamamlanmayacaktır. Bunun süresiz olarak gerçekleşmesini ve makinenizin tüm hesaplama kaynaklarını tüketmesini engelleyen yalnızca sisteminizdeki kontrollerdir. Kendini (veya birbirlerini) özyinelemeli olarak çağırmadıklarından emin olmak için işlevleri değiştirmeniz gerekir.


10

Bu tamamen farklı bir nedenden dolayı başıma geldi. İki sütunu birleştirirken yanlışlıkla süper uzun bir dize oluşturdum:

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

onun yerine

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

Macunun soruna neden olmasını asla beklemediğim için bunu çözmem beni sonsuza dek sürdü.


Burada da aynısı ama bir özet yapıyordum. Böyle vardı: summarize( states = paste0(state,collapse=', ') ). Ne zaman gibi bitti bir şey olmalıdır: summarize( states = paste0(sort(unique(state)),collapse=', ') ). Hedef, her alt grup için mevcut benzersiz durumların virgülle ayrılmış bir listesini elde etmekti.
Richard DiSalvo

4

"C yığını kullanımı sınıra çok yakın" hatasını alma konusunda aynı sorunla karşılaştım (yukarıda user2045093 tarafından belirtilenden başka bir uygulama için olsa da). Zwol'un teklifini denedim ama olmadı.

Kendi sürprizime göre, sorunu, OS X için en yeni R sürümünü (şu anda sürüm 3.2.3) ve OS X için R Studio'nun en yeni sürümünü (şu anda: 0.99.840) yükleyerek çözebildim. R Studio ile çalışıyorum.

Umarım bu size de yardımcı olabilir.


1
Daha yüksek bir R sürümüne geçtim. Bir kez çalıştı, ancak hata yeniden ortaya çıktı ve şimdi tutarlı. Yardım!
murphy1310

2

Buradaki bir sorun, fkendi içinde aramak olabilir

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=) ?

1

Herkesin bilgisi için, Windows 7'de (64-bit) R 3.6.1 ile aniden bununla karşılaşıyorum. Bu daha önce bir sorun değildi ve şimdi veriyi "kaydetmeye (.)" Veya hatta bir "save.image (.)" Yapmaya çalıştığımda yığın sınırları her yerde ortaya çıkıyor gibi görünüyor. Sanki serileştirme bu yığınları uçuruyor.

3.6.0'a geri dönmeyi ciddi olarak düşünüyorum. Orada olmadı.


1

Benimki belki daha benzersiz bir durumdur, ancak tam olarak bu sorunu yaşayan birkaç kişiye yardımcı olabilir:

Durumumun alan kullanımıyla kesinlikle ilgisi yok, yine de R şunları verdi:
C stack usage is too close to the limit

Temel işlevin yükseltmesi olan tanımlanmış bir işleve sahiptim:

saveRDS ()

Ancak,
yanlışlıkla, bu tanımlanmış işlev saveRDS()yerine çağrıldı safe_saveRDS().
Böylece, bu tanımı geçtikten sonra, kodun gerçekte kullandığı satıra geldiğindesaveRDS(...) (yükseltilmiş olanı değil, orijinal temel sürümü çağıran), yukarıdaki hatayı verdi ve ezildi.

Bu nedenle, bazı kaydetme işlevini çağırırken bu hatayı alıyorsanız, yanlışlıkla bunun üzerinden geçip geçmediğinize bakın.


0

Martin Morgan'ın yazdığı gibi ... Sorun, özyinelemenin çok derinlerine inmenizdir. Özyineleme hiç yakınsamıyorsa, kendi başınıza kırmanız gerekir. Umarım bu kod çalışacaktır çünkü test edilmemiştir. Ancak burada en azından nokta açık olmalıdır.

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)
}

0

Aynı soruna neden olmanın başka bir yolu:

library(debug)
mtrace(lapply)

Özyinelemeli arama burada o kadar açık değil.


0

Plot_ly kullanıyorsanız, hangi sütunları geçtiğinizi kontrol edin. Görünüşe göre POSIXdt / ct sütunları için, plotly'ye geçmeden önce as.character () kullanmanız gerekir, yoksa bu istisnayı alırsınız!


0

Genellikle source("path/to/file/thefile.R")bir R betiğinin üstüne yorumlanmış bir satır eklerim, örneğin thefile.R, çalıştırmak için bunu kolayca terminale kopyalayıp yapıştırabilirim. Dosyayı çalıştırmak, dosyayı çalıştıran, dosyayı çalıştıran dosyayı çalıştırdığından, satırı yorumlamayı unutursam bu hatayı alıyorum ...

Sebep buysa, çözüm basit: satırı yorumlayın.


0

Sorunları burada listelediğimizden emin değilim ama benim başıma geldi leaflet() . Bir datesütunun sınıfta olduğu bir veri çerçevesini eşlemeye çalışıyordum POSIXlt. POSIXctSorunu çözmek için geri dönmek .


0

Linux'ta, bunu yaparak yığının ve memlock belleğinin boyutunu kalıcı olarak artırdım:

sudo vi /etc/security/limits.conf 

Ardından, dosyanın sonuna aşağıdaki satırları ekleyin.

* soft memlock unlimited
* hard memlock unlimited

* soft stack unlimited
* hard stack unlimited
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.