2

在 Debian 10 上,我有 2 个带有 NVlink 硬件组件的 GPU 卡 RTX A6000,我希望受益于这两张卡的潜在组合功能。

目前,我有以下由 Makefile 调用的 magma.make :

CXX = nvcc -std=c++17 -O3
LAPACK = /opt/intel/oneapi/mkl/latest
LAPACK_ANOTHER=/opt/intel/mkl/lib/intel64
MAGMA = /usr/local/magma
INCLUDE_CUDA=/usr/local/cuda/include
LIBCUDA=/usr/local/cuda/lib64

SEARCH_DIRS_INCL=-I${MAGMA}/include -I${INCLUDE_CUDA} -I${LAPACK}/include
SEARCH_DIRS_LINK=-L${LAPACK}/lib/intel64 -L${LAPACK_ANOTHER} -L${LIBCUDA} -L${MAGMA}/lib

CXXFLAGS = -c -DMAGMA_ILP64 -DMKL_ILP64 -m64 ${SEARCH_DIRS_INCL}

LDFLAGS = ${SEARCH_DIRS_LINK} -lmkl_intel_lp64 -lmkl_gnu_thread -lmkl_core -lgomp -lcuda -lcudart -lcublas -lmagma -lpthread -lm -ldl 

SOURCES = main_magma.cpp XSAF_C_magma.cpp
EXECUTABLE = main_magma.exe

当我执行我的代码时,我有内存错误,因为在这段代码中,我尝试逆矩阵 size 120k x 120k

如果我们仔细观察,120k x 120k 矩阵需要双精度:120k x 120k x 8 字节,因此差不多 108GB。

隐含的函数不能接受单精度。

不幸的是,我有 2 个 48GB 的​​ NVIDIA GPU 卡:

问题 :

从计算的角度或从编码的角度来看,有没有办法合并 2 个 GPU 卡的 2 个内存(将提供 96GB)以反转这些大矩阵?

我正在使用MAGMA这样的编译和反演例程:

// ROUTINE MAGMA IMPLEMENTED
void matrix_inverse_magma(vector<vector<double>> const &F_matrix, vector<vector<double>> &F_output) {

  // Index for loop and arrays
  int i, j, ip, idx;

  // Start magma part
  magma_int_t m = F_matrix.size();
  if (m) {
  magma_init (); // initialize Magma
  magma_queue_t queue=NULL;
  magma_int_t dev=0;
  magma_queue_create(dev ,&queue );
  double gpu_time , *dwork; // dwork - workspace
  magma_int_t ldwork; // size of dwork
  magma_int_t *piv, info; // piv - array of indices of inter -
  magma_int_t mm=m*m; // size of a, r, c
  double *a; // a- mxm matrix on the host
  double *d_a; // d_a - mxm matrix a on the device
  double *d_c; // d_c - mxm matrix c on the device
 
  magma_int_t ione = 1;
  magma_int_t ISEED [4] = { 0,0,0,1 }; // seed
  magma_int_t err;
  const double alpha = 1.0; // alpha =1
  const double beta = 0.0; // beta=0
  ldwork = m * magma_get_dgetri_nb( m ); // optimal block size
  // allocate matrices
  err = magma_dmalloc_cpu( &a , mm ); // host memory for a

  for (i = 0; i<m; i++){
    for (j = 0; j<m; j++){
      idx = i*m + j;
      a[idx] = F_matrix[i][j];
      //cout << "a[" << idx << "]" << a[idx] << endl;
    }
  }
  err = magma_dmalloc( &d_a , mm ); // device memory for a
  err = magma_dmalloc( &dwork , ldwork );// dev. mem. for ldwork
  piv=( magma_int_t *) malloc(m*sizeof(magma_int_t ));// host mem.

  magma_dsetmatrix( m, m, a, m, d_a, m, queue); // copy a -> d_a

  magma_dgetrf_gpu( m, m, d_a, m, piv, &info);
  magma_dgetri_gpu(m, d_a, m, piv, dwork, ldwork, &info);

  magma_dgetmatrix( m, m, d_a , m, a, m, queue); // copy d_a ->a

  for (i = 0; i<m; i++){
    for (j = 0; j<m; j++){
      idx = i*m + j;
      F_output[i][j] = a[idx];
    }
  }
  // SAVE ORIGINAL
  free(a); // free host memory
  free(piv); // free host memory
  magma_free(d_a); // free device memory
  magma_queue_destroy(queue); // destroy queue
  magma_finalize (); 
  // End magma part
  }
}

如果这不可能直接使用两个 GPU 卡之间的 NVlink 硬件组件来实现,我们可以找到哪种解决方法来允许这种矩阵反转?

编辑 :

@user2357112supportsMonica. 感谢您的快速答复。是的,如您所见,我意识到我没有足够的内存来存储 120k x 120k。但我们的目标是以 60k x 60k 矩阵为例,大概是 54GB:在这种情况下,我怎样才能合并两个 48GB GPU 卡的能力,以便能够反转这个 54GB 矩阵?我正在使用岩浆。

如果我可以将 GPU 内存与 2 张卡合并,也许第三张 48GB 的​​ GPU 卡可以让我反转 120k x 120k:你怎么看?

4

1 回答 1

1

我不是 GP/GPU 计算方面的专家,但如果你能将两个计算设备组合成一个设备,我会感到非常惊讶。至少我认为使用标准库是不可能的。如果您考虑一下,它首先会破坏使用 GPU 的目的。

但是,我会说,一旦使用非常大的矩阵,就会遇到很多问题,这会使教科书的逆运算在数值上不稳定。解决这个问题的正常方法是根本不存储逆矩阵。通常你只需要一个逆矩阵就可以解决

Ax = b(求解 x)
Ax - b = 0(齐次形式)

可以在没有逆A的情况下解决

我建议您首先阅读 C/C++ 中的数值配方的逆矩阵章节。这是一个标准文本,带有示例代码,可从Amazon等处广泛获得。这些文本假定 CPU 实现,但是......

一旦您了解了这些算法,您可能会(或可能不会)发现能够发出两个并行的非逆矩阵运算对您很有用。然而,本文(和其他文本)中描述的算法无论如何都比任何蛮力操作快几个数量级。

于 2022-01-04T14:58:01.223 回答