Take the 2-minute tour ×

I have writen a program that can be summarized as follows:

def loadHugeData():
    #load it
    return data

def processHugeData(data, res_queue):
    for item in data:
        #process it

def writeOutput(outFile, res_queue):
    with open(outFile, 'w') as f
        while res!='END':

res_queue = multiprocessing.Queue()

if __name__ == '__main__':
    p = multiprocessing.Process(target=writeOutput, args=(outFile, res_queue))
    processHugeData(data, res_queue)

The real code (especially ´writeOutput()´) is a lot more complicated. ´writeOutput()´ only uses these values that it takes as its arguments (meaning it does not reference ´data´)

Basically it loads a huge dataset into memory and processes it. Writing of the output is delegated to a sub-process (it writes into multiple files actually and this takes a lot of time). So each time one data item gets processed it is sent to the sub-process trough res_queue which in turn writes the result into files as needed.

The sub-process does not need to access, read or modify the data loaded by ´loadHugeData()´ in any way. The sub-process only needs to use what the main process sends it trough ´res_queue´. And this leads me to my problem and question.

It seems to me that the sub-process gets it's on copy of the huge dataset (when checking memory usage with ´top´). Is this true? And if so then how can i avoid id (using double memory essentially)?

I am using Python 2.6 and program is running on linux.

share|improve this question
Can you restructure your code to use iterators instead of loading all that loadHugeData in ? It would seem that you could if it's as it seems load/process/enqueue/dequeue/write –  sotapme Feb 7 '13 at 11:55
The "hugeData" is unfortunately a tab-separated txt file basically containing a sparse array. And I need "random access" to this data based on the line number during processing. Therefore loading it into memory (with sparse array specific optimisations) makes processing a lot faster. –  anti666 Feb 7 '13 at 12:04
It might be massively over-engineering to suggest using something like `beanstalkd to do the process integration but it would be interesting to know if it helped/scaled/perfomed. As usual other people's problems are always more interesting. –  sotapme Feb 7 '13 at 13:14
add comment

1 Answer

up vote 3 down vote accepted

The multiprocessing module is effectively based on the fork system call which creates a copy of the current process. Since you are loading the huge data before you fork (or create the multiprocessing.Process), the child process inherits a copy of the data.

However, if the operating system you are running on implements COW (copy-on-write), there will only actually be one copy of the data in physical memory unless you modify the data in either the parent or child process (both parent and child will share the same physical memory pages, albeit in different virtual address spaces); and even then, additional memory will only be allocated for the changes (in pagesize increments).

You can avoid this situation by calling multiprocessing.Process before you load your huge data. Then the additional memory allocations will not be reflected in the child process when you load the data in the parent.

share|improve this answer
Faster than me well done. Linux is COW so the moment the parent process writes to the data, the data will be duplicated. If the parent process only reads the data then there will only be one instance of the data BUT top (I'm almost sure) will show the data as belonging to both processes. meminfo should provide more accurate numbers on memory use. –  Eli Algranti Feb 7 '13 at 11:39
Indeed. I think the most common OS are COW these days (I was just trying to be as generic as possible). Great feature but often causes confusion when interpreting the output of process-based memory reporting tools (i.e. top, ps, etc...). meminfo on Linux will report correctly as will pmap on Solaris; no idea about Windows though :) –  isedev Feb 7 '13 at 11:46
Note also that every Python object contains a reference count that is modified whenever the object is accessed. So, just reading a data structure can cause COW to copy. –  Janne Karila Feb 7 '13 at 11:46
Not sure about accessed. You probably mean referenced, no? (i.e. a = SomeObject, b = a) –  isedev Feb 7 '13 at 11:48
Ty for the answer. Calling multiprocessing.Process before loading the data seems to have solved the issue. I will look into meminfo aswell. –  anti666 Feb 7 '13 at 11:58
show 2 more comments

Your Answer


