我有三个大清单.首先包含bitarrays(模块bitarray 0.8.0),另外两个包含整数数组.
l1=[bitarray 1, bitarray 2, ... ,bitarray n]
l2=[array 1, array 2, ... , array n]
l3=[array 1, array 2, ... , array n]
Run Code Online (Sandbox Code Playgroud)
这些数据结构需要相当多的RAM(总共约16GB).
如果我使用以下方式启动12个子流程:
multiprocessing.Process(target=someFunction, args=(l1,l2,l3))
Run Code Online (Sandbox Code Playgroud)
这是否意味着将为每个子流程复制l1,l2和l3,或者子流程是否会共享这些列表?或者更直接,我会使用16GB或192GB的RAM吗?
someFunction将从这些列表中读取一些值,然后根据读取的值执行一些计算.结果将返回到父进程.someIunction不会修改列表l1,l2和l3.
因此,我认为子流程不需要也不会复制这些巨大的列表,而只是与父级共享它们.这意味着由于linux下的写时复制方法,该程序将占用16GB的RAM(无论我启动多少个子进程)?我是正确的还是我错过了会导致列表被复制的内容?
编辑:在阅读了关于这个主题的更多内容后,我仍然感到困惑.一方面,Linux使用copy-on-write,这意味着不会复制任何数据.另一方面,访问该对象将改变其重新计数(我仍然不确定为什么以及这意味着什么).即便如此,是否会复制整个对象?
例如,如果我定义someFunction如下:
def someFunction(list1, list2, list3):
i=random.randint(0,99999)
print list1[i], list2[i], list3[i]
Run Code Online (Sandbox Code Playgroud)
是否使用此函数意味着将为每个子流程完全复制l1,l2和l3?
有没有办法检查这个?
EDIT2在子流程运行的同时读取更多内容并监视系统的总内存使用情况后,似乎确实为每个子流程复制了整个对象.它似乎是因为引用计数.
在我的程序中实际上不需要l1,l2和l3的引用计数.这是因为l1,l2和l3将保留在内存中(未更改),直到父进程退出.在此之前,不需要释放这些列表使用的内存.事实上,我确信引用计数将保持在0以上(对于这些列表和这些列表中的每个对象),直到程序退出.
所以现在问题变成了,我怎样才能确保不会将对象复制到每个子进程?我可以禁用这些列表和这些列表中的每个对象的引用计数吗?
EDIT3只是一个额外的说明.子进程并不需要修改l1,l2并l3或在这些列表中的任何对象.子进程只需要能够引用其中一些对象,而不会导致为每个子进程复制内存.
这个问题来自这里.
我有三个包含python对象(l1,l2和l3)的大型列表.这些列表是在程序启动时创建的,它们总共需要16GB的RAM.该程序将专门用于linux.
创建后,我不需要以任何方式或形式修改这些列表或这些列表中的对象.它们必须保留在内存中,直到程序退出.
我在我的程序中使用os.fork()和多处理模块来生成多个子进程(当前最多20个).这些子流程中的每一个都需要能够读取三个列表(l1,l2和l3).
我的程序在其他方面工作正常并且非常快.但是我遇到内存消耗问题.由于Linux上的写时复制方法,我希望每个子进程都可以使用这三个列表而不将它们复制到内存中.但是情况并非如此,因为引用任何这些列表中的任何对象都会增加相关的引用计数,从而导致整个内存页面被复制.
所以我的问题是:
我可以禁用引用计数l1,l2以及l3这些列表中的所有对象吗?基本上将整个对象(包括诸如引用计数之类的元数据)设置为只读,以便在任何情况下都不会被修改(我认为,这将允许我利用写入时复制).
目前我担心我被迫转移到另一种编程语言来完成这项任务,因为我目前不需要的"功能"(引用计数),但仍然强加给我并导致不必要的问题.
我写了一个程序,可以总结如下:
def loadHugeData():
#load it
return data
def processHugeData(data, res_queue):
for item in data:
#process it
res_queue.put(result)
res_queue.put("END")
def writeOutput(outFile, res_queue):
with open(outFile, 'w') as f
res=res_queue.get()
while res!='END':
f.write(res)
res=res_queue.get()
res_queue = multiprocessing.Queue()
if __name__ == '__main__':
data=loadHugeData()
p = multiprocessing.Process(target=writeOutput, args=(outFile, res_queue))
p.start()
processHugeData(data, res_queue)
p.join()
Run Code Online (Sandbox Code Playgroud)
真正的代码(特别是writeOutput())要复杂得多.writeOutput()仅使用它作为参数的这些值(意味着它不引用data)
基本上它将一个巨大的数据集加载到内存中并对其进行处理.输出的写入被委托给一个子进程(它实际写入多个文件,这需要花费很多时间).因此,每次处理一个数据项时,它都会通过res_queue发送到子进程,res_queue会根据需要将结果写入文件.
子进程不需要以loadHugeData()任何方式访问,读取或修改加载的数据.子流程只需要使用主流程发送它的内容res_queue.这引出了我的问题和疑问.
在我看来,子流程将它放在庞大数据集的副本上(当检查内存使用情况时top).这是真的?如果是这样,我怎么能避免id(基本上使用双内存)?
我使用的是Python 2.6,程序在linux上运行.
我正在使用 python 运行一些 shell 脚本、RScript、python 程序等。这些程序可能会运行很长时间,并且可能会向 stdout 和 stderr 输出大量(日志记录)信息。我正在使用以下(Python 2.6)代码,它运行良好:
stdoutFile=open('stdout.txt', 'a')
stderrFile=open('stderr.txt', 'a')
subprocess.call(SHELL_COMMAND, shell=True, stdout=stdoutFile, stderr=stderrFile)
stdoutFile.close()
stderrFile.close()
Run Code Online (Sandbox Code Playgroud)
这主要是记录到文件的信息,并且该信息可以在很长一段时间内生成。因此我想知道是否可以在每一行前面加上日期和时间?
例如,如果我当前要记录:
Started
Part A done
Part B done
Finished
Run Code Online (Sandbox Code Playgroud)
那么我希望它是:
[2012-12-18 10:44:23] Started
[2012-12-18 12:26:23] Part A done
[2012-12-18 14:01:56] Part B done
[2012-12-18 22:59:01] Finished
Run Code Online (Sandbox Code Playgroud)
注意:修改我运行的程序不是一个选项,因为这个 python 代码有点像这些程序的包装器。
我有一个包含数百行和数十W列的表:
Column1 | Column2_W | Column3_W | ColumnX_W
123 | A | B | x
223 | A | NULL | NULL
Run Code Online (Sandbox Code Playgroud)
如何选择它以使输出为:
Column1 | W
123 | A
123 | B
123 | x
223 | A
Run Code Online (Sandbox Code Playgroud)
编辑:我很清楚我正在使用可怕的数据库"设计".不幸的是我无法改变它.这个问题实际上是我今天提出的一个更大问题的一部分.我明天会尝试给定的想法
我需要使用python从大型txt文件中获取N行.这些文件基本上是制表符分隔的表.我的任务有以下限制:
目前我已经编写了以下代码:
inputSize=os.path.getsize(options.input)
usedPositions=[] #Start positions of the lines already in output
with open(options.input) as input:
with open(options.output, 'w') as output:
#Handling of header lines
for i in range(int(options.header)):
output.write(input.readline())
usedPositions.append(input.tell())
# Find and write all random lines, except last
for j in range(int(args[0])):
input.seek(random.randrange(inputSize)) # Seek to random position in file (probably middle of line)
input.readline() # Read the line (probably incomplete). Next input.readline() results in a complete line.
while input.tell() …Run Code Online (Sandbox Code Playgroud) python ×5
datetime ×1
large-data ×1
large-files ×1
line ×1
linux ×1
logging ×1
random ×1
readline ×1
refcounting ×1
select ×1
sql ×1
stdout ×1
subprocess ×1