1

我正在尝试对 parselmouth PRAAT 函数应用多处理来提取多个函数。

 import concurrent.futures
 import time

 with concurrent.futures.ProcessPoolExecutor(max_workers=8) as executor:
        futures = [executor.submit(self.f1, ),executor.submit(self.f2, )]
        for future in concurrent.futures.as_completed(futures):
            data = future.result()

但是我得到了这个错误,这是多处理时不可拾取的对象的问题:

The above exception was the direct cause of the following exception:

 TypeError Traceback (most recent call last)
 <ipython-input-15-2dea24cd4bf1> in <module>
  2 strr = time.time()
  3 FeatureCalculateobj = FeatureCalculate(os.path.join(root,'P1_A2.wav'),async_flag=True)
  4 print(time.time()-strr)
  5 

  <ipython-input-13-f5b7e5b9fab3> in __init__(self, path, async_flag)
 26 
 27         if async_flag:
                self.main()
 29         else:
 30             self.str_pauses = self.extract_pauses_unasync()

  <ipython-input-13-f5b7e5b9fab3> in main(self)
176             futures = [executor.submit(self.jitter_shimmer, )]
177             for future in concurrent.futures.as_completed(futures):
                data = future.result()
179             print(data)
180 

 ~/miniconda3/envs/via_3.7/lib/python3.7/concurrent/futures/_base.py in result(self, timeout)
        raise CancelledError()
427           elif self._state == FINISHED:
                 return self.__get_result()
429 
430             self._condition.wait(timeout)

  ~/miniconda3/envs/via_3.7/lib/python3.7/multiprocessing/queues.py in _feed(buffer, notempty, send_bytes, writelock, close, ignore_epipe, onerror, queue_sem)
234 
235                         # serialize the data before acquiring the lock
                 obj = _ForkingPickler.dumps(obj)
237              if wacquire is None:
238                   send_bytes(obj)



~/miniconda3/envs/via_3.7/lib/python3.7/multiprocessing/reduction.py 
 in dumps(cls, obj, protocol)
 49     def dumps(cls, obj, protocol=None):
 50         buf = io.BytesIO()
            cls(buf, protocol).dump(obj)
 52         return buf.getbuffer()
 53 

         TypeError: can't pickle parselmouth.Sound objects
  cls(buf, protocol).dump(obj) TypeError: can't pickle parselmouth.Sound objects

虽然我没有将 parselmouth.Sound 对象作为参数传递给类方法,但我仍然收到此错误

4

2 回答 2

0

您可以使用 Python 的多处理模块在 Parselmouth 中进行多处理,并确保在每个进程中创建声音,如果在 Windows 上在if __name__ == __main__语句中创建进程也是如此。asyncio 不像 Parselmouth 那样用于受 CPU 限制的进程,因此 multiprocessing 更合适。这是一个工作示例:

import parselmouth
from multiprocessing import Pool, cpu_count
from glob import glob

# First make a function to multiprocess
def get_mean_pitch(filename):
    try:
        pitch = parselmouth.Sound(filename).to_pitch()
        mean_pitch = parselmouth.praat.call(pitch, "Get mean", 0, 0, "Hertz")
    except:
        mean_pitch = 0
    return mean_pitch

# Then make a list of wav files to iterate over
sound_filenames = sorted(glob("*.wav")

# Get the number of CPUs on the machine
cpus = cpu_count()

# Create a pool of CPUs
pool = Pool(cpus)

# Map the function over the list of files
results = pool.map(get_pitch, sound_filenames)
于 2021-10-08T14:57:44.387 回答
0

嗯,显然 Parselmouth 对象还不支持 pickle 协议(请参阅错误消息TypeError: can't pickle parselmouth.Sound objects)。我从来没有在多处理的上下文中考虑过它,但是对于这些类型的用例来说,确实值得实现它!

我会看看我是否可以在下一个版本中获得它。有些东西告诉我这不应该太难:-)

同时,您可能会做的是将文件写入临时目录,然后在multiprocessing?的每个单独进程中再次读取它。

于 2020-06-26T12:39:46.920 回答