识别处理器核心或工作者ID并行python

时间:2013-12-18 22:36:18

标签: python windows parallel-python

我正在并行运行进程,但需要为每个要写入的cpu进程创建一个数据库。我只想要在每个服务器上分配cpu的数据库,所以将100个作业写入3个可以合并的数据库。

我是否可以将每个工作人员识别为工作人员ID号或核心ID?

def workerProcess(job):
  if workerDBexist(r'c:\temp\db\' + workerid):
    ##processjob into this database
  else:
    makeDB(r'c:\temp\db\' + workerid)
    ##first time this 'worker/ core' used, make DB then process

import pp
ppservers = ()
ncpus = 3
job_server = pp.Server(ncpus, ppservers=ppservers)

for work in 100WorkItems:
  job_server.submit(workerProcess, (work,))

1 个答案:

答案 0 :(得分:2)

据我所知,pp在其API中没有任何此类功能。

如果您使用stdlib模块,那将使您的生活更轻松 - 例如,multiprocessing.Pool采用initializer参数,您可以使用该参数为每个进程初始化数据库,然后可以作为每个任务可以使用的变量。

但是,有一个相对简单的解决方法。

每个进程都有一个唯一的(至少在运行时)进程ID。*在Python中,您可以使用os.getpid()访问当前进程的进程ID。因此,在每项任务中,您都可以执行以下操作:

dbname = 'database{}'.format(os.getpid())

然后使用dbname打开/创建数据库。我不知道“数据库”是指dbm文件,sqlite3文件,MySQL服务器上的数据库,还是什么。您可能需要,例如,在父级中创建tempfile.TemporaryDirectory,将其传递给所有子级,并将它们os.path.join传递给dbname(因此在完成所有子级之后,您可以获取os.listdir(the_temp_dir))中的所有内容。


这个问题是,如果pp.Server重启其中一个进程,你最终会得到4个数据库而不是3个。可能不是一个大问题,但你的代码应该处理这种可能性。 (IIRC,pp.Server通常不会重新启动流程,除非您通过restart=True,但可能会这样做,例如,如果其中一个崩溃了。)

但是,如果(实际情况是这样)你实际上是在一个全新的流程中运行每个任务,而不是使用3个流程池?好吧,那么你最终会得到与进程一样多的数据库,这可能不是你想要的。你真正的问题是你没有使用3个进程池,这是你应该修复的。但是,还有其他方法可以得到你想要的东西吗?也许

例如,假设您创建了三个锁,每个数据库一个,可能是锁定文件。然后,每个任务都可以执行此伪代码:

for i, lockfile in enumerate(lockfiles):
    try:
        with lockfile:
            do stuff with databases[i]
            break
    except AlreadyLockedError:
        pass
else:
    assert False, "oops, couldn't get any of the locks"

如果您实际上可以自己锁定数据库(使用flock,或使用相关数据库的某些API等),事情就更容易了:只需尝试依次连接它们,直到其中一个成功为止。

只要您的代码实际上不是segfaulting等,**如果您实际上从未运行过3个以上的任务,那么所有3个锁定文件都无法锁定,因此您可以保证得到一个。


*这不太正确,但这对你的目的来说已经足够了。例如,在Windows上,每个进程都有一个唯一的HANDLE,如果您询问pid,那么如果它还没有,则会生成一个。{1}}。在某些* nixes上,每个线程都有一个唯一的线程 ID,而进程的pid是第一个线程的线程ID。等等。但就您的代码而言,每个流程都有一个唯一的pid,这才是最重要的。

**即使您的代码 崩溃,您也可以处理它,它会更复杂。例如,使用pidfiles而不是空的lockfiles。获取pidfile上的读锁定,然后尝试升级到写锁定。如果失败,请从文件中读取pid,并检查是否存在任何此类进程(例如,在* nix上,如果os.kill(pid, 0)引发,则没有此类进程),如果是,则强制中断锁定。无论哪种方式,现在你都有一个写锁,所以把你的pid写到文件中。