在Debian 10上工作时,我有两个GPU卡RTX A6000,带有1TB RAM的NVlink硬件组件,我想利用这两个卡和1TB RAM潜在的组合功能。
目前,我有以下magma.make被Makefile调用:
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
当我执行代码时,我会有内存错误,因为在这个代码中,我试图逆大小为120k x 120k
的矩阵。
如果我们仔细观察,120k x 120k矩阵需要双倍精度:120k x 120 k x 8个字节,因此最多需要108GB。
隐含的函数不能接受单精度。
不幸的是,我有两个NVIDIA GPU卡,每个48GB:
问题:
从计算的角度或从编码的角度来看,有没有一种方法可以合并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硬件组件来实现,我们可以找到哪种解决方法来允许这种矩阵反转?
编辑:
HPC工程师告诉我:
"最简单的方法是使用Makefiles,直到我们弄清楚如何cmake可以支持这一点。如果你这样做了,你可以更换通过magma_dgetrf进行LAPACKE_ddgetrf。MAGMA将在内部使用一个GPU内存不足算法,填充因子矩阵,即使它是大并且不会进入GPU的存储器">
这是否意味着我必须找到Makefile的适当标志才能使用magma_dgetrf而不是LAPACKE_ddgetrf?
对于第二句话,据说
"MAGMA将在内部使用一个内存不足算法的GPU填充因子矩阵";
这是否意味着如果我的矩阵如果超过48GB,那么MAGMA将能够将其余部分填充到第二GPU A6000或RAM中,并执行完整矩阵的反转?
请让我知道在我的情况下使用哪些标志来正确构建MAGMA。
我确实这么认为:
$ mkdir build && cd build
$ cmake -DUSE_FORTRAN=ON
-DGPU_TARGET=Ampere
-DLAPACK_LIBRARIES="/opt/intel/oneapi/intelpython/latest/lib/liblapack.so"
-DMAGMA_ENABLE_CUDA=ON ..
$ cmake --build . --config Release
我不是GP/GPU计算方面的专家,但如果你能将两个计算设备组合成一个设备,我会感到非常惊讶。至少我认为使用标准库是不可能的。如果你仔细想想,它一开始就有点违背了使用GPU的目的。
然而,我想说的是,一旦你使用非常大的矩阵,你就会遇到很多问题,这会使教科书中的逆运算在数值上不稳定。解决这个问题的正常方法是永远不要存储逆矩阵。通常你只需要一个逆矩阵就可以求解
Ax=b(求解x(
Ax-b=0(同构形式(
无需逆即可解决
我建议你从阅读C/C++中的数值公式的逆矩阵章节开始。这是一个标准文本,带有示例代码,可从亚马逊等网站广泛获得。这些文本假设CPU实现,但。。。
一旦你了解了这些算法,你可能会(也可能不会(发现能够发出两个并行的非逆矩阵运算对你很有用。然而,本文(和其他文本(中描述的算法比任何暴力操作都快几个数量级。