当内存不足时,Jupyter Lab会冻结计算机-如何防止它发生?

时间:2019-10-15 18:11:31

标签: python jupyter-notebook jupyter-lab

我最近开始使用Jupyter Lab,我的问题是我使用的是非常大的数据集(通常,数据集本身大约是计算机RAM的1/4)。经过几次转换后,另存为新的Python对象,我倾向于耗尽内存。问题是,当我接近可用的RAM限制并执行需要另一个RAM空间的任何操作时,计算机将冻结,而修复它的唯一方法是重新启动它。这是Jupyter Lab / Notebook中的默认行为,还是我应该设置的某些设置?通常,我希望程序崩溃(例如在RStudio中),而不是整个计算机

7 个答案:

答案 0 :(得分:4)

绝对最可靠的解决方案是使用Docker容器。您可以指定要分配给Jupyter的内存量,并且如果容器用完了内存,那也没什么大不了的(只记得经常保存即可,但这不用多说)。

This blog将带您到达目的地。还有一些不错的说明,可以从此处免费提供的,官方维护的Jupyter映像之一设置Jupyter Lab:

https://medium.com/fundbox-engineering/overview-d3759e83969c

,然后您可以按照教程中的说明将docker run命令修改为(例如3GB):

docker run --memory 3g <other docker run args from tutorial here>

有关docker内存选项的语法,请参阅以下问题:

What unit does the docker run "--memory" option expect?

答案 1 :(得分:3)

如果您使用的是Ubuntu,请查看OOM杀手,您可以从here中获取信息

您可以使用earlyoom。可以根据需要进行配置,例如earlyoom -s 90 -m 15将启动earlyoom,并且当交换大小小于%90并且内存小于%15时,它将终止导致OOM的进程并防止整个系统冻结。您还可以配置进程的优先级。

答案 2 :(得分:2)

我还在Jupyter Lab上处理非常大的数据集(3GB),并且在Labs上也遇到了同样的问题。 目前尚不清楚您是否需要维护对预转换数据的访问,如果不需要,我已经开始使用del未使用的大型数据框变量,如果我不需要它们的话。 del从您的内存中删除变量。编辑**:我遇到的问题有多种可能。当我使用远程jupyter实例时,以及在执行大型转换时,在spyder中我也会更经常遇到这种情况。

例如

df = pd.read('some_giant_dataframe') # or whatever your import is
new_df = my_transform(df)
del df # if unneeded.

Jake,您可能还会发现此thread on large data workflows有用。我一直在研究Dask来帮助进行内存存储。

我在spyder和jupyter中注意到,冻结通常发生在运行大型内存控制台的另一个控制台中。至于为什么它只是冻结而不是崩溃,我认为这与内核有关。有几个记忆issues open in the IPython github-#10082和#10117似乎最相关。一位用户here建议在jedi中禁用制表符完成功能或更新jedi。

在10117中,他们建议检查get_ipython().history_manager.db_log_output的输出。我遇到了同样的问题,我的设置是正确的,但是值得检查

答案 3 :(得分:1)

您还可以在云中使用笔记本,例如Google Colab here。他们为推荐的RAM提供了便利,默认情况下是对Jupyter Notebook的支持。

答案 4 :(得分:0)

我认为您应该使用块。像这样:

public class Project
    {
        public int ID { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public DateTime DateAdded { get; set; }

        public int? ParentId { get; set; }
        public int? DepartmentId { get; set; }
        public int? CompanyId { get; set; }


        public virtual Department Department { get; set; }
        public virtual Company Company { get; set; }

        public virtual Project Parent { get; set; }

        public virtual List<Project> Activities { get; set; }
        public virtual List<TimeSheetProject> TimeSheetProjects { get; set; }
        public virtual List<ProjectFile> ProjectFiles { get; set; }

    }

有关更多信息,请查看:https://towardsdatascience.com/why-and-how-to-use-pandas-with-large-data-9594dda2ea4c

我建议不要再添加列表(可能RAM会再次过载)。您应该在该for循环中完成工作。

答案 5 :(得分:0)

我将总结以下question中的答案。 您可以限制程序的内存使用量。在下面将是函数ram_intense_foo()。在调用之前,您需要调用函数limit_memory(10)

import resource
import platform
import sys
import numpy as np 

def memory_limit(percent_of_free):
    soft, hard = resource.getrlimit(resource.RLIMIT_AS)
    resource.setrlimit(resource.RLIMIT_AS, (get_memory() * 1024 * percent_of_free / 100, hard))

def get_memory():
    with open('/proc/meminfo', 'r') as mem:
        free_memory = 0
        for i in mem:
            sline = i.split()
            if str(sline[0]) == 'MemAvailable:':
                free_memory = int(sline[1])
                break
    return free_memory

def ram_intense_foo(a,b):
    A = np.random.rand(a,b)
    return A.T@A

if __name__ == '__main__':
    memory_limit(95)
    try:
        temp = ram_intense_foo(4000,10000)
        print(temp.shape)
    except MemoryError:
        sys.stderr.write('\n\nERROR: Memory Exception\n')
        sys.exit(1)

答案 6 :(得分:-4)

没有理由查看大型数据帧的整个输出。查看或处理大型数据框将不必要地使用大量计算机资源。

无论您做什么,都可以微型完成。当数据帧较小时,对数据进行编码和处理要容易得多。处理大数据的最佳方法是创建一个仅占大数据帧一小部分或一小部分样本的新数据帧。然后,您可以浏览数据并在较小的数据帧上进行编码。浏览数据并使代码正常工作后,只需在较大的数据框中使用该代码即可。

最简单的方法是使用head()函数从数据帧中获取前n行,即第一行的数量。头函数仅打印n行数。您可以通过在大型数据框上使用head函数来创建小型数据框。在下面,我选择选择前50行并将其值传递给small_df。假定BigData是一个数据文件,该数据文件来自您为此项目打开的库。

library(namedPackage) 

df <- data.frame(BigData)                #  Assign big data to df
small_df <- head(df, 50)         #  Assign the first 50 rows to small_df

这在大多数情况下都会起作用,但是有时大数据框会附带预排序的变量或已分组的变量。如果大数据是这样的,那么您需要从大数据中随机抽取行样本。然后使用以下代码:

df <- data.frame(BigData)

set.seed(1016)                                          # set your own seed

df_small <- df[sample(nrow(df),replace=F,size=.03*nrow(df)),]     # samples 3% rows
df_small                                                         # much smaller df