对文件夹中的文件列表进行子集化以应用 python 函数

问题描述 投票:0回答:1

我有一个功能,需要一个包含only图像而没有其他内容的文件夹的路径。但是,我有 3000 多个包含图像的文件夹,还有其他文件(随机 .txt 文件、RTSTRUC 文件等)。

对于每个文件夹,我使用 sh.copy() 将图像移动到 tmp 文件夹中,然后将我的函数指向该文件夹。但我遇到了很长的运行时间。我尝试用 sh.copyfiles() 缩短也发现它很慢。我尝试与多处理库并行化,但遇到了问题,因为每个子进程使用相同的临时文件夹并且存在无意的混合和匹配!

有什么想法吗?

for file in glob.glob(dicom_dir + "/*IMG*"):
    shutil.copy(file,tmp_dicom_folder)

提供令人望而却步的运行时间。

有没有办法让我使用临时文件夹进行并行化而不会遇到此问题?为每个进程创建一个临时文件夹听起来很混乱。

python runtime
1个回答
0
投票

使用符号链接而不是副本。为要并行运行的每个进程创建一个临时目录。如果这是 CPU 密集型图像处理,则每个 CPU 略少于一个进程是一个合理的起点,但可能会因各种原因(例如 GPU 使用情况)而改变。

列出您想要处理的文件并将它们的符号链接分散到目录中。在每个符号链接目录上运行程序的副本,每个目录都会获得工作负载的子集。

import itertools
import multiprocessing as mp
import tempfile
from pathlib import Path
import subprocess as subp

dicom_dir = Path("tmp/test")

# assuming each image process takes 1 cpu and you don't want
# to commit all of them... Note: There may be better ways to
# get an accurate count.

cpus = int(mp.cpu_count() * .80) or 1

# build tmp directory for each cpu, populate with symlinks to
# image files and run one process per directory.

with tempfile.TemporaryDirectory() as tmpdir:
    root = Path(tmpdir)
    cpudirs = [root/f"sym_{x}" for x in range(cpus)]
    for cpudir in cpudirs:
        cpudir.mkdir()
    count = 0
    for count, (target, cpudir) in enumerate(
            zip(dicom_dir.glob("*IMG*"), 
            itertools.cycle(cpudirs))):
        (cpudir/target.name).symlink_to(target.absolute())
    if count < len(cpudirs):
        # there were fewer IMG than cpus, remove what we didn't use
        del cpudirs[count:]
    # TODO: This is a naive way to run the commands and would be slow
    #       if there is a lot of stdout/err to consume.
    processes = [subp.Popen(["the command", cpudir.absolute()])
        for cpudir in cpudirs]
    for proc in processes:
        proc.communicate()
© www.soinside.com 2019 - 2024. All rights reserved.