实施多处理以处理HPC上的大量输入/输出

时间:2017-04-10 15:43:21

标签: python numpy input multiprocessing processing-efficiency

我需要处理超过1000万个光谱数据集。数据结构如下:大约有1000个.fits(.fits是一些数据存储格式)文件,每个文件包含大约600-1000个光谱,其中每个光谱中有大约4500个元素(因此每个文件返回~1000个* 4500矩阵)。这意味着如果我要遍历1000万个条目,每个光谱将被重复读取大约10次(或者每个文件将被重复读取大约10,000次)。虽然相同的光谱重复读取大约10次,但它并不重复,因为每次我提取相同光谱的不同片段。在@Paul Panzer的帮助下,我已经避免多次读取同一个文件了。

我有一个目录文件,其中包含我需要的所有信息,例如坐标xy,半径r,力量s等。目录还包含用于定位我将要阅读的文件(由n1n2标识)以及我将使用该文件中的哪些光谱(由n3标识)的信息。

我现在的代码是:

import numpy as np
from itertools import izip
import itertools
import fitsio

x = []
y = []
r = []
s = []
n1 = []
n2 = []
n3 = []
with open('spectra_ID.dat') as file_ID, open('catalog.txt') as file_c:
    for line1, line2 in izip(file_ID,file_c):
        parts1 = line1.split()
        parts2 = line2.split()
        n1.append(int(parts1[0]))
        n2.append(int(parts1[1]))
        n3.append(int(parts1[2]))
        x.append(float(parts2[0]))         
        y.append(float(parts2[1]))        
        r.append(float(parts2[2]))
        s.append(float(parts2[3]))  

def data_analysis(n_galaxies):
    n_num = 0
    data = np.zeros((n_galaxies), dtype=[('spec','f4',(200)),('x','f8'),('y','f8'),('r','f8'),('s','f8')])

    idx = np.lexsort((n3,n2,n1))
    for kk,gg in itertools.groupby(zip(idx, n1[idx], n2[idx]), lambda x: x[1:]):
        filename = "../../data/" + str(kk[0]) + "/spPlate-" + str(kk[0]) + "-" + str(kk[1]) + ".fits"
        fits_spectra = fitsio.FITS(filename)
        fluxx = fits_spectra[0].read()
        n_element = fluxx.shape[1]
        hdu = fits_spectra[0].read_header()
        wave_start = hdu['CRVAL1']
        logwave = wave_start + 0.0001 * np.arange(n_element)
        wavegrid = np.power(10,logwave)

        for ss, plate1, mjd1 in gg:
            if n_num % 1000000 == 0:
                print n_num
            n3new = n3[ss]-1
            flux = fluxx[n3new]
            ### following is my data reduction of individual spectra, I will skip here
            ### After all my analysis, I have the data storage as below:
            data['spec'][n_num] = flux_intplt
            data['x'][n_num] = x[ss]
            data['y'][n_num] = y[ss]
            data['r'][n_num] = r[ss]
            data['s'][n_num] = s[ss]

            n_num += 1

    print n_num
    data_output = FITS('./analyzedDATA/data_ALL.fits','rw')
    data_output.write(data)

我有点理解多处理需要删除一个循环,但是将索引传递给函数。但是,我的函数中有两个循环,这两个循环高度相关,所以我不知道如何处理。由于此代码中最耗时的部分是从磁盘读取文件,因此多处理需要充分利用内核来一次读取多个文件。任何人都能对我有所了解吗?

1 个答案:

答案 0 :(得分:0)

  1. 摆脱global varsglobal vars无法使用processes
  2. 将您的多个global vars合并到一个容器类或dict中, 将相同光谱的不同片段分配到一个数据集中
  3. 将您的global with open(...移至def ...
  4. data_output分隔为自己的def ...
  5. 尝试第一次,不使用multiprocessing,这个概念:

    for line1, line2 in izip(file_ID,file_c):
        data_set = create data set from (line1, line2)
        result = data_analysis(data_set)
        data_output.write(data)  
    
  6. 考虑使用2 processes一个用于文件读取,另一个用于文件写入。 将multiprocessing.Pool(processes=n)用于data_analysis 使用processes

  7. multiprocessing.Manager().Queue()之间进行通信