使用NumPy进行快速矩阵更新

3

我的问题是,我需要从一个以特定格式保存的文件中读取大约50M行的文本。

x1 "\t" x2 "\t" .. x10 "\t" count

然后计算矩阵A,其中组成部分为A[j][i] = 所有行的计数 * x_i * x_j之和。

我尝试了两种方法,都是逐行读取文件:

1)将A保持为Python矩阵并在for循环中更新:

  for j in range(size):
    for i in range(size):
      A[j][i] += x[j] * x[i] * count

2) 将A转换为numpy数组,并使用numpy.add进行更新:

  numpy.add(A, count * numpy.outer(x, x))

令我惊讶的是,第二种方法比第一种慢了约30%。而且两种方法都非常缓慢 - 整个文件需要大约10分钟... 是否有办法加快矩阵的计算速度?也许有一些函数可以从文件中完全读取数据(或大块读取),而不是逐行读取?有什么建议吗?

1
"\t"是制表符,而不是文件中实际的文字表示。你可以将整个文件读入内存吗? - undefined
你可以在计算 i 的范围之前延迟乘以 count,因为 a1*c + a2*c + ... + an*c = (a1 + a2 + ... + an) * c - undefined
1
在这10分钟中,有多少时间用于读取文件,而不是处理? - undefined
1
只是为了澄清一下:在您的示例中,size的值是10,也就是说A是一个10x10的矩阵,并且您要对这些操作重复执行5000万次?能否展示完整的代码? - undefined
有没有可能以更快的加载速度“重新保存”文件?例如,使用.npy格式的文件?当然,这只有在您多次读取同一个文件而不是每次读取不同文件时才可能。 - undefined
显示剩余3条评论
3个回答

2

一些想法:

  • 使用pandas.read_csvC引擎读取文件。与np.genfromtxt相比,它的速度要快得多,因为该引擎是c / Cython优化的。
  • 您可以将整个文件读入内存,然后进行计算。这是最简单的方法,但从效率的角度来看,您的CPU将大部分时间处于等待输入的空闲状态。这段时间可以更好地用于计算。
  • 您可以尝试逐行读取和处理(例如使用cvs模块)。虽然io仍然是瓶颈,但最终您将已经处理了文件。问题在于,由于Python开销,您仍然会有一些效率损失。
  • 可能最佳组合是使用pandas.read_csv 并设置iterator chunk_size 参数以按块读取,并每次处理一些块。我敢打赌,有一个最佳块大小将击败其他方法。

1

你的矩阵是对称的,使用第一种方法只计算上半部分(每行只需 55 次计算,而非 100 次)。

第二种方法速度较慢。我不知道为什么,但如果你实例化了 5000 万个小的 ndarrays,可能会成为瓶颈,可以考虑使用单个 ndarray 并复制每行数据。

x = np.zeros((11,))
for l in data.readlines():
    x[:] = l.split()
    A+=np.outer(x[:-1],x[:-1])*x[-1]

可能会导致加速。

0
根据您的机器可用内存大小,您可以尝试使用正则表达式来解析值,并使用numpy的重塑和切片功能来应用计算。如果内存不足,可以考虑类似的方法,将文件分成1M行的块进行读取。
txt = open("C:/temp/input.dat").read()
values = re.split("[\t|\n]", txt.strip())

thefloats = [ float(x) for x in values]
mat = np.reshape(thefloats, (num_cols, num_rows))

for i in range(len(counts)):
    mat[:-1,i] *= counts[-1,i]   

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接