如何使用CuPy在GPU上运行Python?

5
我正在尝试使用 CuPy 库在 GPU 上执行 Python 代码。然而,当我运行 nvidia-smi 时,找不到任何 GPU 进程。

nvidia-smi output

这是代码:
    import numpy as np
    import cupy as cp
    from scipy.stats import rankdata

    def get_top_one_probability(vector):
      return (cp.exp(vector) / cp.sum(cp.exp(vector)))

    def get_listnet_gradient(training_dataset, real_labels, predicted_labels):
      ly_topp = get_top_one_probability(real_labels)
      cp.cuda.Stream.null.synchronize()
      s1 = -cp.matmul(cp.transpose(training_dataset), cp.reshape(ly_topp, (np.shape(cp.asnumpy(ly_topp))[0], 1)))
      cp.cuda.Stream.null.synchronize()
      exp_lz_sum = cp.sum(cp.exp(predicted_labels))
      cp.cuda.Stream.null.synchronize()
      s2 = 1 / exp_lz_sum
      s3 = cp.matmul(cp.transpose(training_dataset), cp.exp(predicted_labels))
      cp.cuda.Stream.null.synchronize()
      s2_s3 = s2 * s3 # s2 is a scalar value
      s1.reshape(np.shape(cp.asnumpy(s1))[0], 1)
      cp.cuda.Stream.null.synchronize()
      s1s2s3 = cp.add(s1, s2_s3)
      cp.cuda.Stream.null.synchronize()
      return s1s2s3

    def relu(matrix):
      return cp.maximum(0, matrix)

    def get_groups_id_count(groups_id):
      current_group = 1
      group_counter = 0
      groups_id_counter = []
      for element in groups_id:
        if element != current_group:
          groups_id_counter.append((current_group, group_counter))
          current_group += 1
          group_counter = 1
        else:
          group_counter += 1
      return groups_id_counter

    def mul_matrix(matrix1, matrix2):
      return cp.matmul(matrix1, matrix2)

if mode == 'train': # Train MLP
  number_of_features = np.shape(training_set_data)[1]

  # Input neurons are equal to the number of training dataset features
  input_neurons = number_of_features
  # Assuming that number of hidden neurons are equal to the number of training dataset (input neurons) features + 10
  hidden_neurons = number_of_features + 10

  # Weights random initialization
  input_hidden_weights = cp.array(np.random.rand(number_of_features, hidden_neurons) * init_var)
  # Assuming that number of output neurons is 1
  hidden_output_weights = cp.array(np.float32(np.random.rand(hidden_neurons, 1) * init_var))

  listwise_gradients = np.array([])

  for epoch in range(0, 70):
    print('Epoch {0} started...'.format(epoch))
    start_range = 0
    for group in groups_id_count:
      end_range = (start_range + group[1]) # Batch is a group of words with same group id
      batch_dataset = cp.array(training_set_data[start_range:end_range, :])
      cp.cuda.Stream.null.synchronize()
      batch_labels = cp.array(dataset_labels[start_range:end_range])
      cp.cuda.Stream.null.synchronize()
      input_hidden_mul = mul_matrix(batch_dataset, input_hidden_weights)
      cp.cuda.Stream.null.synchronize()
      hidden_neurons_output = relu(input_hidden_mul)
      cp.cuda.Stream.null.synchronize()
      mlp_output = relu(mul_matrix(hidden_neurons_output, hidden_output_weights))
      cp.cuda.Stream.null.synchronize()
      batch_gradient = get_listnet_gradient(batch_dataset, batch_labels, mlp_output)
      batch_gradient = cp.mean(cp.transpose(batch_gradient), axis=1)
      aggregated_listwise_gradient = cp.sum(batch_gradient, axis=0)
      cp.cuda.Stream.null.synchronize()
      hidden_output_weights = hidden_output_weights - (learning_rate * aggregated_listwise_gradient)
      cp.cuda.Stream.null.synchronize()
      input_hidden_weights = input_hidden_weights - (learning_rate * aggregated_listwise_gradient)
      cp.cuda.Stream.null.synchronize()
      start_range = end_range

      listwise_gradients = np.append(listwise_gradients, cp.asnumpy(aggregated_listwise_gradient))

  print('Gradients: ', listwise_gradients)

我使用cp.cuda.Stream.null.synchronize(),因为我读到这个语句可以确保代码在继续执行下一行之前在GPU上完成执行。

有人能帮助我在GPU上运行代码吗?谢谢提前。

1个回答

7

Cupy可以在不同的设备上运行您的代码。您需要选择与GPU关联的正确设备ID,以便您的代码能够在其上执行。我认为其中一个设备是您的CPU(可能带有ID 0 )。您可以使用以下命令检查当前设备ID:

x = cp.array([1, 2, 3])
print(x.device)

要获取您计算机上已识别设备的数量:
print(cp.cuda.runtime.getDeviceCount())

例如,将您当前的设备更改为ID 1:

cp.cuda.Device(1).use()

设备ID是从0开始编号的,因此如果您有3个设备,您将得到一个ID集合{0, 1, 2}。

谢谢你的回答。cp.cuda.runtime.getDeviceCount()返回值为1,那么我需要使用索引0上的设备,对吗? - pairon
如果你只有一张GPU,那么是的,我猜索引0就是另一个设备,希望它是你的GPU。 - Victor Deleau
1
好的,谢谢。我正在尝试使用设备0,但是nvidia-smi仍然显示GPU上没有进程。 - pairon
我不知道为什么。向量化计算在你的GPU上一定会更快。如果你尝试在每个设备上运行代码,最快的一定是你的GPU。 - Victor Deleau
我正在从CuPy转向MinPy,这是另一种在GPU上实现NumPy的方法。然而,我发现GPU仅被使用了8%。难道NumPy限制了GPU的使用? - pairon
MinPy/Numpy并不限制GPU的使用。您的GPU拥有数百个核心,旨在进行大规模并行计算,而深度学习无法完全从中受益。在GPU上训练大型DL模型通常不会使用超过其可用资源的10%。您可以进行优化并获得一些1%左右的提升,但这基本上就是全部了。 - Victor Deleau

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