multiprocessing.Pool can handle this. By default, the pool will create one process per CPU on your machine. Since they all will spend some time waiting on the disk to read the files, its a good way to mostly commit your machine. Its something you can tweak if either CPU usage or disk usage makes your machine unresponsive to other programs.

The pool divides work into chunks much like your example, but in the case of heavy processing on potentially variable sized files, a chunksize of 1 can avoid you wating for the tall-pole process to complete.

import multiprocessing as mp

def do_the_work(filename):
    pass

master_list = [file1, file2, fil3, ...filen]
with mp.Pool() as pool:
    results = pool.map(do_the_work, master_list, chunksize=1)
Answer from tdelaney on Stack Overflow
🌐
KDnuggets
kdnuggets.com › 2022 › 07 › parallel-processing-large-file-python.html
Parallel Processing Large File in Python - KDnuggets
There is a better way to process large files by splitting them into batches and processing them parallel. Let’s start by creating a batch function that will run a clean_function on a single batch of values. def proc_batch(batch): return [ clean_text(text) for text in batch ] The function below will split the file into multiple batches based on the number of workers.
Discussions

arcpy - Processing multiple files simultanously using python - Geographic Information Systems Stack Exchange
I have 11000 point shapefiles to run Near tool on against another point shapefile. I am looking for a way to process 10 files at the same time. Is there a way to process so many files using Pytho... More on gis.stackexchange.com
🌐 gis.stackexchange.com
python - Processing multiple data files simultaneously using multiple cores - Stack Overflow
I have multiple data files that I process using python Pandas libraries. Each file is processed one by one, and only one logical processor is used when I look at Task manager (it is at ~95%, and the rest are within 5%) Is there a way to process data files simultaneously? If so, is there a way to utilize the other logic processors to do that? ... from multiprocessing import Process def YourCode(filename, otherdata): # Do your stuff if __name__ == '__main__': #Post process files in parallel ... More on stackoverflow.com
🌐 stackoverflow.com
python - parallel processing of files from a directory - Code Review Stack Exchange
This code does parallel processing of files read from a directory. It divides the directory into 'core' number of file chunks and process those chunks in parallel. 'cores' is the number of cores in... More on codereview.stackexchange.com
🌐 codereview.stackexchange.com
October 30, 2020
Running multiple python files in parallel - Stack Overflow
The following is my code. It's quite simple and straight forward, and the mission is to run three files at the same time. When I ran it, it only runs the last processes (each file should generate ... More on stackoverflow.com
🌐 stackoverflow.com
🌐
Reddit
reddit.com › r/learnpython › running script on multiple files in parallel
r/learnpython on Reddit: Running script on multiple files in parallel
November 30, 2022 -

I have a very large file that I need to process, and a python script that will process it. The script just loops through the lines of the file, does the calculation on each line, and prints the processed line to an output file. However, since the calculation is merely line by line I was hoping to speed this up somewhat by breaking the file into equal-sized chunks and processing the chunks in parallel. I have 12 cores on my machine.

I can think of two naive ways to do this:

  1. Use a multiprocessing pool to run the script on the X chunks in parallel (I'm not very experienced with multiprocessing but I have successfully used it in the past)

  2. Simply execute the script on each chunk and then background the process, until I have X jobs running in the background.

I doubt these are exactly equivalent, though, and I was wondering what the differences are and which I could expect to be faster.

If anyone could give me some advice/clarity I'd appreciate it!

Edit: I can think of better ways to do this but they would involve rewriting this old script and I'm trying to get an example project done as quickly as possible, so I'm looking for a quick and dirty parallelization of the straightforward looping code for now, and I'll refactor things later.

🌐
Python
docs.python.org › 3 › library › multiprocessing.html
multiprocessing — Process-based parallelism
Due to this, the multiprocessing module allows the programmer to fully leverage multiple processors on a given machine. It runs on both POSIX and Windows. The multiprocessing module also introduces the Pool object which offers a convenient means of parallelizing the execution of a function across multiple input values, distributing the input data across processes (data parallelism).
Top answer
1 of 2
4

If you are restricted to windows you can write a DOS sript and run it in parallel as decribed parallel execution of shell processes

If can run in linux there is a procedure pretty well worked out using gnu-parallel. I did something similar for QGIS described in more detail at How to run processing commands in parallel in QGIS

Although the examples I give are for QGIS they would work in principle for arcpy in DOS too. ie If you can generate the the proces you neeed to carry out on one file as a BASH script which incorporates the file names as inputs, then you can use gnu parallel in linux or a parallel DOS script in DOS to handle the parallel work. Based on Oles answer to: parallelising-gis-operations-in-pyqgis eg:

Assuming you had a bash script which could run your "near" process as follows

my_standalone_script.py /path/to/a/point/shpfile.shp /path/to/another/point/file.shp /path/to/output/file.shp

You could install gnu parallel and run the script in parallel with:

find /path/to/point/shpfiles -type f -name *.shp | parallel my_standalone_script.py {} /path/to/another_point_file.shp /path/to-output/folder/neared_{/}.shp

As far as reasonable time is concerned gnu parallel will carry out the operation about as well as could be be achieved given any hardware limitations. You can even cluster more computers together and have them all carry out some of the solution each. (provided you can install the software required on each unit).

2 of 2
2

Esri has a useful blog post on utilizing Python's multiprocessing module. In many cases the multiprocessing module works fine with Esri's arcpy site package, mostly for embarrassingly parallel geoprocessing tasks that do not require any shared data (e.g. feature classes in a file geodatabase) among the workers.

I have run into so many problems developing arcpy based multiprocessing applications that I rarely bother any more and usually either focus on streamlining and optimizing existing code or opting for open-source multiprocessing solutions.

In any case, when using the multiprocessing module, you will need to optimize the multiprocessing on your machine as there will be a threshold where the workers max out your system resources resulting in diminishing returns.

Top answer
1 of 2
1

If your file names are in a list, you could use this code:

from multiprocessing import Process

def YourCode(filename, otherdata):
    # Do your stuff

if __name__ == '__main__':
    #Post process files in parallel
    ListOfFilenames = ['file1','file2', ..., 'file1000']
    ListOfProcesses = []
    Processors = 20 # n of processors you want to use
    #Divide the list of files in 'n of processors' Parts
    Parts = [ListOfFilenames[i:i + Processors] for i in xrange(0, len(ListOfFilenames), Processors)]

    for part in Parts:
        for f in part:
            p = multiprocessing.Process(target=YourCode, args=(f, otherdata))
            p.start()
            ListOfProcesses.append(p)
        for p in ListOfProcesses:
            p.join()
2 of 2
0

You can process the different files in different threads or in different processes.

The good thing of python is that its framework provides tools for you to do this:

from multiprocessing import Process

def process_panda(filename):
    # this function will be started in a different process
    process_panda_import()
    write_results()

if __name__ == '__main__':
    p1 = Process(target=process_panda, args=('file1',))
    # start process 1
    p1.start() 
    p2 = Process(target=process_panda, args=('file2',))
    # starts process 2
    p2.start() 
    # waits if process 2 is finished
    p2.join()  
    # waits if process 1 is finished
    p1.join()  

The program will start 2 child-processes, which can be used do process your files. Of cource you can do something similar with threads.

You can find the documentation here: https://docs.python.org/2/library/multiprocessing.html

and here:

https://pymotw.com/2/threading/

🌐
Nurda Bolatov
nurdabolatov.com › parallel-processing-large-file-in-python
Parallel processing large file in Python · Nurda Bolatov
May 8, 2021 - Takes file_name, chunk_start (character position to start processing from), chunk_end (character position to end at) as input ... We could refactor these functions by decoupling the logic but let’s keep them as is to understand the higher-level picture. ... def parallel_read(file_name): # Maximum number of processes we can run at a time cpu_count = mp.cpu_count() file_size = os.path.getsize(file_name) chunk_size = file_size // cpu_count # Arguments for each chunk (eg.
Find elsewhere
🌐
YouTube
youtube.com › chee wan go
python- read multiple files and process line by line parallel - YouTube
AboutPressCopyrightContact usCreatorsAdvertiseDevelopersTermsPrivacyPolicy & SafetyHow YouTube worksTest new features · © 2024 Google LLC
Published: October 24, 2019
Views: 294
Top answer
1 of 1
3

The python standard library offers two process pools to simplify what you're trying to achieve: multiprocessing.Pool (as mentioned by @RootTwo) and concurrent.futures.ProcessPoolExecutor.

I personally like the second one (despite its more limited API) because you can replace it with a ThreadPoolExecutor without changing the rest of the code. Threads are better suited if your processing is I/O bound, because inter-process communication is slow and processes are slower to start (especially on Windows). With the concurrent.futures API, you can easily swap the two and test which one works better.

There are some other ways you can improve the code, most notably:

  1. If you're on Python 3.x as you should be, I suggest the use of pathlib instead of os.path.
  2. Put code from the if __name__ == "__main__": into a "main" function to make automated testing easier.
  3. Use snake_case instead of camelCase as that's the accepted standard for Python.
  4. (Opinion) If you're on python 3.x, you could also use type annotations to improve the readability of the code.

With this in mind, I would rewrite your code as:

from pathlib import Path
from concurrent.futures import ProcessPoolExecutor, as_completed
from typing import Iterable

def get_files(directory: Path) -> Iterable[Path]:
    # Using glob simplifies the code in these cases.
    return (file for file in directory.glob("**/*") if file.is_file())

def foo(file: Path):
    ...

# This can be easily called from a test
def process_files(directory: Path):
    # I am using sum, so that the result is computed lazily and we
    # do not need to build a list of all files. If the directory is
    # very large, this could save a lot of memory.
    # Since get_files returns a one-shot generator, we cannot
    # save it to a variable and reuse it here and below.
    file_count = sum(1 for _ in get_files(directory))
    
    with concurrent.futures.ProcessPoolExecutor() as executor:
        futures = executor.map(foo, get_files(directory))
        # Reading the value returned by the executor is very
        # important, because exceptions happening in the `foo`
        # function will be captured and not be raised until the
        # value is read, thus obfuscating the errors.
        #        
        # Another nice solution for the progress would be
        # using the library tqdm.
        for i, _ in enumerate(as_completed(futures)):
            print(f"Processed file {i+1} / {file_count}")

if __name__ == "__main__":
    process_files(Path(""))
🌐
Stack Overflow
stackoverflow.com › questions › 32620973 › running-multiple-python-files-in-parallel › 44763030
Running multiple python files in parallel - Stack Overflow
import multiprocessing import subprocess def worker(file): subprocess.call(["python", file]) if __name__ == '__main__': files = ["launch_day_t1.py","launch_day_t2.py","launch_day_t3.py"] for i in files: p = multiprocessing.Process(target=worker(i)) p.start() As you can see I have three files ("launch_day_t1.py","launch_day_t2.py" and "launch_day_t3.py") that I wish to run. My question is that whether is this the best way to run parallel scripts (if it is), or is there a better approach?
🌐
Gist.ly
gist.ly › youtube-summarizer › python-parallel-processing-creating-multiple-files-dynamically
Python Parallel Processing: Creating Multiple Files Dynamically
September 26, 2024 - In this article, we've seen a practical example of how to implement parallel processing in Python within a Databricks environment. By leveraging the power of multi-threading, we can dynamically create multiple files simultaneously, thereby improving ...
Top answer
1 of 1
1

When considering performance of any program, you have to work out if the performance is bound by I/O (memory, disk, network, whatever) or Compute (core count, core speed, etc).

If I/O is the bottleneck, there's no point having multiple processes, a faster CPU, etc.

If the computation is taking up all the time, then it is worth investing in multiple processes, etc. "Computation time" is often diagnosed as being the problem, but on closer investigation turns out to be limited by the computer's memory bus speed, not the clock rate of the cores. In such circumstances adding multiple processes can make things worse...

Check

You can check yours by doing some performance profiling of your code (there's bound to be a whole load of profiling tools out there for Python).

My Guess

Most of the time these days it's I/O that's the bottleneck. If you don't want to profile your code, betting on a faster SSD is likely the best initial approach.

Unsolvable Computer Science Problem

The architectural features of modern CPUs (L1, L2, L3 cache, QPI, hyperthreads) are all symptoms of the underlying problem in computer design; cores are too quick for the I/O we can wrap around them.

For example, the time taken to transfer 1 byte from SDRAM to the core is exceedingly slow in comparison to the core speed. One just has to hope that the L3, L2 and L1 cache subsystems have correctly predicted the need for that 1 byte and have already fetched it ahead of time. If not, there's a big delay; that's where hyperthreading can help the overall performance of the computer's other processes (they can nip in and get some work done), but does absolutely nothing for the stalled program.

Data fetched from files or networks is very slow indeed.

File System Caching

In your case it sounds like you have 1 single input file; that will at least get cached in RAM by the OS (provided it's not too big).

You may be tempted to read it into memory yourself; I wouldn't bother. If it's large you would be allocating a large amount of memory to hold it, and if that's too big for the RAM in the machine the OS will swap some of that RAM out to the virtual memory page file anyway, and you're worse off than before. If it's small enough there's a good chance the OS will cache the whole thing for you anyway, saving you the bother.

Written files are also cached, up to a point. Ultimately there's nothing you can do if "total process time" is taken to mean that all the data is written to disk; you'd be having to wait for the disk to complete writing no matter what you did in memory and what the OS cached.

The OS's filesystem cache might give an initial impression that file writing has completed (the OS will get on with consolidating the data on the actual drive shortly), but successive runs of the same program will get blocked once that write cache is full.

If you do profile your code, be sure to run it for a long time (or repeatedly), to make sure that the measurements made by the profiler reveal the true underlying performance of the computer. If the results show that most of the time is in file.Read() or file.Write()...

🌐
Quora
quora.com › Can-I-read-several-files-in-parallel-in-Python
Can I read several files in parallel in Python? - Quora
Answer (1 of 3): Yes. You can open multiple files at the same time - write a loop that steps through each file line by line : [code]from itertools import zip_longest, count with open(‘file1.txt’) as f1, open(‘file2.txt’) as f2: from index, line1,line2 in zip_Longest(count(), f1,f2):...
🌐
Pratapvardhan
pratapvardhan.com › notes › python › read-files-parallel-merge
python: read files in parallel and merge them | Pratap Vardhan
import pandas as pd from multiprocessing import Pool files = folderPath.glob('*.csv') with Pool() as pool: df = pd.concat(pool.map(pd.read_csv, files))
🌐
Reddit
reddit.com › r/learnpython › multiprocessing/threading for multiple file processing.
r/learnpython on Reddit: Multiprocessing/Threading for multiple file processing.
November 22, 2023 -

Hi, everyone!

So, I think that I'm pretty decent with Python, but I've never had any formal training/studying. And now, it is the first time I need to improve the performance of my program. My program computes a lot of different things and processing one file takes maybe 2 minutes on a decent computer.

While the complete process is pretty complex, the issue I'm facing right now is right at the start:

First, I convert a "PDB" file into a different one, calling another software with subprocess. Then, I compute several affinity maps on this new file, which are saved to a folder created for the PDB file.

The issue is that, since it is a long process, and I need to analyze multiple files, I decided to process all the files simultaneously.

For that, I do the following:

def generate_ply_file(pdbfile):
print("Processing: ", pdbfile)
subprocess.run(["python", "../src/generate_ply_surface.py", pdbfile]) 

if __name__ == "__main__":

    pdbfiles = glob.glob("*.pdb")

num_processes = multiprocessing.cpu_count()


with multiprocessing.Pool(processes=num_processes) as pool:
    pool.map(generate_ply_file, pdbfiles)

At this point, I run the program, and cool, looks like it's all running at the same time. The issue is that I see some of the files being generated returning weird errors, and when I go look at the generated directories, files that should be in folder A are in folder B, and so on.

I checked for os calls changing directories and making files non-reachable or something like that but there are none, and to be honest, I do not understand how multiprocessing works so I don´t know if that is even an issue.

Finally, my questions. How to fix this? Is multiprocessing the correct way? Should I use something different? What can I do?

Thanks for any help you guys can provide!

🌐
Medium
dmesh-io.medium.com › load-data-in-parallel-with-python-aa579df45c64
Parallel data loading with python | by Jorge Machado | Medium
April 23, 2022 - Passing it as the argument has the benefit that you can write multiple enrich_functions and the loading part stays the same. If you need a progress bar you can just use tqdm. Everything stays the same, only the function load_data changes to the following: Using Spark IMHO is the best way. Yes, it has a downside in that you need to install java, but it handles most of the things out of the box.
🌐
YouTube
youtube.com › corey schafer
Python Multiprocessing Tutorial: Run Code in Parallel Using the Multiprocessing Module - YouTube
In this video, we will be learning how to use multiprocessing in Python. This video is sponsored by Brilliant. Go to https://brilliant.org/cms to sign up for...
Published: September 20, 2019
Views: 228K