gpt4 book ai didi

python - 在 Python 中使用 OpenCL 并行化循环

转载 作者:行者123 更新时间:2023-12-01 09:10:35 25 4
gpt4 key购买 nike

我在矩阵y中有一个给定的数据集,我想用它来训练不同的SOM。 SOM 是一维的(一条线),其神经元数量各不相同。我首先训练大小为 N=2 的 SOM,最后训练 N=NMax,总共得到 NMax-2+1 个 SOM 。对于每个 SOM,我希望在训练结束后存储权重,然后再继续下一个 SOM。

这里使用 PyOpenCL 的全部意义在于,每个外部循环都是独立于其他循环的。也就是说,对于 N 的每个值,脚本并不关心 N 采用其他值时会发生什么。手动更改 N 值运行脚本 NMax-2+1 次可能会得到相同的结果。

考虑到这一点,我希望能够使用 GPU 同时执行这些独立迭代中的每一个,从而显着减少所花费的时间。不过,速度的增加将小于 1/(NMax-2+1),因为每次迭代都比之前的迭代更昂贵,对于较大的 N 值,进行更多计算。

有没有办法“翻译”此代码以在 GPU 上运行?我以前从未使用过 OpenCL,所以请告诉我这是否太宽泛或愚蠢,以便我可以提出更具体的问题。该代码是独立的,所以请随意尝试一下。开头声明的四个常量可以更改为您喜欢的任何内容(假设 NMax > 1 和所有其他都严格为正数) .

import numpy as np
import time

m = 3 # Dimension of datapoints
num_points = 2000 # Number of datapoints
iterMax = 150 # Maximum number of iterations
NMax = 3 # Maximum number of neurons
#%%
np.random.seed(0)
y = np.random.rand(num_points,m) # Generate always the same dataset
sigma_0 = 5 # Initial value of width of the neighborhood function
eta_0 = 1 # Initial value of learning rate
w = list(range(NMax - 1))
wClusters = np.zeros((np.size(y,axis = 0),NMax - 1)) # Clusters for each N

t_begin = time.clock() # Start time
for N in range(NMax-1): # Number of neurons for this iteration
w[N] = np.random.uniform(0,1,(N+2,np.size(y,axis=1))) - 0.5 # Initialize weights
iterCount = 1
while iterCount < iterMax:
# Mix up the input patterns
mixInputs = y[np.random.permutation(np.size(y,axis = 0)),:]
# Sigma reduction
sigma = sigma_0 - (sigma_0/(iterMax + 1)) * iterCount
s2 = 2*sigma**2
# Learning rate reduction
eta = eta_0 - (eta_0/(iterMax + 1)) * iterCount
for selectedInput in mixInputs: # Pick up one pattern
# Search winning neuron
aux = np.sum((selectedInput - w[N])**2, axis = -1)
ii = np.argmin(aux) # Neuron 'ii' is the winner
jjs = abs(ii - list(range(N+2)))
dists = np.min(np.vstack([jjs , abs(jjs-(N+2))]), axis = 0)
# Update weights
w[N] = w[N] + eta * np.exp((-dists**2)/s2).T[:,np.newaxis] * (selectedInput - w[N])
print(N+2,iterCount)
iterCount += 1
# Assign each datapoint to its nearest neuron
for kk in range(np.size(y,axis = 0)):
aux = np.sum((y[kk,] - w[N])**2,axis=-1)
ii = np.argmin(aux) # Neuron 'ii' is the winner
wClusters[kk,N] = ii + 1
t_end = time.clock() # End time
#%%
print(t_end - t_begin)

最佳答案

我试图给出一个比较完整的答案。

首先:

此代码可以修改为使用 (py)OpenCL 在 GPU 上运行吗?

很可能是的。

这可以自动完成吗?

不(据我所知)。

我收到的有关 OpenCL 的大多数问题都是这样的:“是否值得将这段代码移植到 OpenCL 以获得加速增益?”您指出,您的外循环独立于其他运行的结果,这使得代码基本上可并行化。在简单的实现中,每个 OpenCL 工作元素将执行相同的代码,但输入参数略有不同。不考虑主机和设备之间数据传输的开销,该方法的运行时间将等于最慢迭代的运行时间。根据外循环中的迭代,这可能会带来巨大的速度增益。只要数字保持相对较小,您就可以尝试 python 中的多处理模块在 CPU 而不是 GPU 上并行化这些迭代。

移植到 GPU 通常只有在要并行运行大量进程(大约 1000 个或更多)时才有意义。因此,就您的情况而言,如果您确实想要极大的速度提升,请查看是否可以并行化循环内的所有计算。例如,您有 150 次迭代和 2000 个数据点。如果您能够以某种方式并行化这 2000 个数据点,则可以提供更大的速度增益,从而证明将整个代码移植到 OpenCL 的工作是合理的。

TL;博士:首先尝试在 CPU 上并行化。如果您发现需要同时运行数百个以上的进程,请转向 GPU。

更新:使用多处理(无回调)在 CPU 上并行化的简单代码

import numpy as np
import time
import multiprocessing as mp

m = 3 # Dimension of datapoints
num_points = 2000 # Number of datapoints
iterMax = 150 # Maximum number of iterations
NMax = 10 # Maximum number of neurons
#%%
np.random.seed(0)
y = np.random.rand(num_points,m) # Generate always the same dataset
sigma_0 = 5 # Initial value of width of the neighborhood function
eta_0 = 1 # Initial value of learning rate
w = list(range(NMax - 1))
wClusters = np.zeros((np.size(y,axis = 0),NMax - 1)) # Clusters for each N

def neuron_run(N):
w[N] = np.random.uniform(0,1,(N+2,np.size(y,axis=1))) - 0.5 # Initialize weights
iterCount = 1
while iterCount < iterMax:
# Mix up the input patterns
mixInputs = y[np.random.permutation(np.size(y,axis = 0)),:]
# Sigma reduction
sigma = sigma_0 - (sigma_0/(iterMax + 1)) * iterCount
s2 = 2*sigma**2
# Learning rate reduction
eta = eta_0 - (eta_0/(iterMax + 1)) * iterCount
for selectedInput in mixInputs: # Pick up one pattern
# Search winning neuron
aux = np.sum((selectedInput - w[N])**2, axis = -1)
ii = np.argmin(aux) # Neuron 'ii' is the winner
jjs = abs(ii - list(range(N+2)))
dists = np.min(np.vstack([jjs , abs(jjs-(N+2))]), axis = 0)
# Update weights
w[N] = w[N] + eta * np.exp((-dists**2)/s2).T[:,np.newaxis] * (selectedInput - w[N])
print(N+2,iterCount)
iterCount += 1
# Assign each datapoint to its nearest neuron
for kk in range(np.size(y,axis = 0)):
aux = np.sum((y[kk,] - w[N])**2,axis=-1)
ii = np.argmin(aux) # Neuron 'ii' is the winner
wClusters[kk,N] = ii + 1

t_begin = time.clock() # Start time
#%%

def apply_async():
pool = mp.Pool(processes=NMax)
for N in range(NMax-1):
pool.apply_async(neuron_run, args = (N,))
pool.close()
pool.join()
print "Multiprocessing done!"

if __name__ == '__main__':
apply_async()

t_end = time.clock() # End time
print(t_end - t_begin)

关于python - 在 Python 中使用 OpenCL 并行化循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51689620/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com