我是stackoverflow的新人,我很高兴发表我的第一个问题。实际上,我是编程领域的新手,但我有一些基本知识,我实际上是在使用Python来解决一个分类问题。我有一大组数据(在我的实际问题中,n=60326),每个向量大约有416维。我需要计算这些不同向量之间的曼哈顿距离,以便根据相似性对我的数据集进行分类(取一个随机参考向量,并将距离介于0和1之间的最接近向量合并在一起)我已经熟悉Kmeans和基本的ML聚类算法…我的实际问题是我需要加速时间使用GPU(CUDA)在开始分类之前首先计算距离矩阵,它的大小为n²(60326 x 60326,我们可以将其减少到n²/2,因为它是一个对称矩阵),所以我的实际问题是如何实现CUDA在这种情况下,我已经安装了CUDA包与Python。在
我从并行CPU的处理开始,它提供了一个内存错误
import pandas as pd
import time
import time
import numpy as np
import random
from scipy.spatial import distance
from sklearn.metrics.pairwise import pairwise_distances
signatures=pd.read_csv("C:\\Users\\YMH1\\Documents\\Reduce Java code\\BOBST.txt", sep=' ',header=None,usecols=[*range(2,417)])
PartName = pd.read_csv('C:\\Users\\YMH1\\Documents\\Reduce Java code\\misumi_new.txt', sep=' ', header=None, usecols=[*range(0,1)])
signatures_vector=np.array(signatures)
PartName_vector=np.array(PartName)
D = pairwise_distances(X = signatures_vector, metric = 'manhattan', n_jobs = -1)
print(D)
现在,我正在尝试实现CUDA,因为它加快了时间,所以我编写了以下代码:
^{pr2}$我的问题是,当我们使用CUDA时,如何定义曼哈顿规范,在def manhattan内部要做什么修改 非常感谢你
根据documentation,
manhattan
距离度量是元素差的绝对值的两个向量之和。在你可能遇到的一个问题是内存空间。如果我们假设距离度量(即矩阵元素)的输出被表示为一个普通的python数量,这可能会占用8个字节的内存。对于指定的维度(60326),这意味着矩阵将占用60326*60326*8字节,这几乎是30GB。即使我们假设你只存储了其中的一半,即使我们假设是32位的绝对差异之和,这仍然需要超过7GB的存储空间。在
当我试图使用sckit learn方法运行这样的测试时,我遇到了麻烦,即使是在一台拥有128GB系统内存的机器上:
在这种情况下,在我的机器上进行计算似乎需要30分钟。输出测试矩阵看起来大致正确,但是python抛出了一个错误,因为一些中间表示是>;2GB。在
内存大小问题也是numba/cuda实现中需要考虑的重要问题之一。在
然而,要执行的操作相对简单。根据我的测试,它可以比numpy/scikit学习方法运行得快得多。在
下面是一个成功的例子:
^{pr2}$在本例中,我将
signatures
向量限制为60000个,而不是60320个,因为较大的数字会导致输出矩阵太大,无法容纳16GB Tesla P100 GPU的可用内存。如果您的GPU内存少于16GB,则此代码将无法正常工作。您需要将问题缩小到更小的签名向量数。将向量分成两组,并在两组之间进行距离计算,以填充整个矩阵,这应该相对简单。在然而,在我的测试机器上的numba代码只需11秒就可以运行,并且对于我正在打印的输出矩阵的非常小的16x16块似乎产生了相同的结果。在
如果我分析一下这段代码,我会发现GPU内核在大约3秒钟内运行,从GPU到CPU的巨大输出矩阵的数据传输时间大约需要6秒,其余的大约是python开销的2秒。在
实际的GPU算法是面向块的。每个块负责将8个矢量与整个矢量阵列进行比较。每个块首先将8个向量加载到共享内存中,然后遍历整个向量数组,根据这8个向量计算曼哈顿距离。块使用块跨步循环来遍历整个数组。在每个循环迭代结束时,与当前比较相对应的8个曼哈顿距离写入输出数组。在
此外,对代码进行了细微的更改,因此只计算对角线上方的矩阵输出值。由于计算是分块进行的,因此不计算对角线上方没有元素的块。这样可以将处理时间减少大约一半,但完整的输出矩阵仍在内存中。因此,上面16x16输出的左下象限全部为零,因为8x8象限完全“低于”对角线,因此跳过了对它的处理,因为问题中已经指出了类似情况。在
相关问题 更多 >
编程相关推荐