无法在我自己的代码中使用 CHOLMOD 和 CUDA 加速

标签 c cuda suitesparse

我正在尝试在 SuiteSparse 4.4.4 中使用 CHOLMODCUDA 加速。我按照用户指南编译,可以成功运行Demo文件夹下的gpu.sh,这说明GPU已经完成了部分工作。但是,当我尝试使用 CHOLMOD 运行自己的代码时,我发现 GPU 调用次数始终为 0。我确实将 Common->useGPU 设置为 1,并且环境变量 CHOLMOD_USE_GPU 也设置为 1。我的 Makefile 如下所示。库路径是正确的。对我有什么建议吗?

实际上我应该提到我只是运行一个最简单的测试用例来求解线性系统。

我尝试了几个来自 UF 稀疏矩阵集合的矩阵,但是 nvprof 显示没有分析 CUDA 应用程序。

我试过的一些矩阵:

bmw7st_1:http://www.cise.ufl.edu/research/sparse/matrices/GHS_psdef/bmw7st_1.html

nd6k: http://www.cise.ufl.edu/research/sparse/matrices/ND/nd6k.html

nd24k: http://www.cise.ufl.edu/research/sparse/matrices/ND/nd24k.html

代码:

#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <assert.h>
#include <sys/time.h>
#include "cholmod.h"

int main (void)
{
    struct timeval t1, t2;
    double elapsedTime;

    const char* matFile = "../bmw7st_1.mtx";
    FILE* fp = fopen(matFile, "r");
    assert(fp != NULL);

    cholmod_sparse *A ;
    cholmod_dense *x, *b;
    cholmod_factor *L ;

    cholmod_common* c = (cholmod_common*)malloc(sizeof(cholmod_common));
    cholmod_start (c) ; /* start CHOLMOD */
    c->useGPU = 1;
    c->supernodal = CHOLMOD_SUPERNODAL;

    A = cholmod_read_sparse (fp, c) ; /* read in a matrix */
    cholmod_print_sparse (A, "A", c) ; /* print the matrix */
    fclose(fp);

    if (A == NULL || A->stype == 0) /* A must be symmetric */
    {
        cholmod_free_sparse (&A, c) ;
        cholmod_finish (c) ;
        return (0) ;
    }

    b = cholmod_ones (A->nrow, 1, A->xtype, c) ; /* b = ones(n,1) */

    gettimeofday(&t1, NULL);
    L = cholmod_analyze (A, c) ; /* analyze */
    cholmod_factorize (A, L, c) ; /* factorize */
    x = cholmod_solve (CHOLMOD_A, L, b, c) ; /* solve Ax=b */
    gettimeofday(&t2, NULL);
    elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0;
    elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0;
    printf("Time: %.4f ms\n", elapsedTime);

    cholmod_free_factor (&L, c) ; /* free matrices */
    cholmod_free_sparse (&A, c) ;
    cholmod_free_dense (&x, c) ;
    cholmod_free_dense (&b, c) ;
    cholmod_finish (c) ; /* finish CHOLMOD */
    return (0) ;
}

生成文件:

CC = gcc

CFLAGS = -g -Wall -O2 \
-lrt -lgfortran \
-gdwarf-2

LIBS = $(CHOLMOD)/Lib/libcholmod.a \
$(AMD)/Lib/libamd.a \
$(COLAMD)/Lib/libcolamd.a \
$(LAPACK)/liblapack.a \
$(OPENBLAS)/lib/libopenblas.so \
$(XERBLA)/libcerbla.a \
$(METIS)/libmetis.a \
$(CAMD)/Lib/libcamd.a \
$(CCOLAMD)/Lib/libccolamd.a \
$(SUITESPARSE)/SuiteSparse_config/libsuitesparseconfig.a \
$(CUDART_LIB) \
$(CUBLAS_LIB)

HEADER_DIR = $(CHOLMOD)/Include
CONFIG_HEADER_DIR = $(SUITESPARSE)/SuiteSparse_config

OBJ_DIR = .

BIN_DIR = .

INCLUDES = -I$(HEADER_DIR) \
-I$(CONFIG_HEADER_DIR)

SRCS = $(shell ls *.c)

OBJS = $(SRCS:.c=.o)

OBJS_BUILD = $(shell ls $(OBJ_DIR)/*.o)

APP = prog

RM = rm -f

all: $(APP)

$(APP): $(OBJS)
        $(CC) $(CFLAGS) -o $(BIN_DIR)/$(APP) $(OBJS_BUILD) $(LIBS)

%.o: %.c $(HEADER_DIR)/*.h $(CONFIG_HEADER_DIR)/*.h
        $(CC) $(CFLAGS) $(INCLUDES) -c $< -o $(OBJ_DIR)/$@

clean:
        $(RM) $(OBJS_BUILD) $(APP)

最佳答案

引用 SuiteSparse 4.4.4 附带的 CHOLMOD UserGuide.pdf 的第 7 节,第 34 页:

Only the long integer version of CHOLMOD can leverage GPU acceleration.

长整数版本的区别在于像 cholmod_l_start 而不是 cholmod_start 这样的 API 调用。

对您的程序进行以下修改:

#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <assert.h>
#include <sys/time.h>
#include "cholmod.h"

int main (void)
{
    struct timeval t1, t2;
    double elapsedTime;

    const char* matFile = "../Matrix/nd6k/nd6k.mtx";
    FILE* fp = fopen(matFile, "r");
    assert(fp != NULL);

    cholmod_sparse *A ;
    cholmod_dense *x, *b;
    cholmod_factor *L ;

    cholmod_common* c = (cholmod_common*)malloc(sizeof(cholmod_common));
    cholmod_l_start (c) ; /* start CHOLMOD */
    c->useGPU = 1;
    c->supernodal = CHOLMOD_SUPERNODAL;

    A = cholmod_l_read_sparse (fp, c) ; /* read in a matrix */
    cholmod_l_print_sparse (A, "A", c) ; /* print the matrix */
    fclose(fp);

    if (A == NULL || A->stype == 0) /* A must be symmetric */
    {
        cholmod_l_free_sparse (&A, c) ;
        cholmod_l_finish (c) ;
        return (0) ;
    }

    b = cholmod_l_ones (A->nrow, 1, A->xtype, c) ; /* b = ones(n,1) */

    gettimeofday(&t1, NULL);
    L = cholmod_l_analyze (A, c) ; /* analyze */
    cholmod_l_factorize (A, L, c) ; /* factorize */
    x = cholmod_l_solve (CHOLMOD_A, L, b, c) ; /* solve Ax=b */
    gettimeofday(&t2, NULL);
    elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0;
    elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0;
    printf("Time: %.4f ms\n", elapsedTime);
    cholmod_l_gpu_stats(c);
    cholmod_l_free_factor (&L, c) ; /* free matrices */
    cholmod_l_free_sparse (&A, c) ;
    cholmod_l_free_dense (&x, c) ;
    cholmod_l_free_dense (&b, c) ;
    cholmod_l_finish (c) ; /* finish CHOLMOD */
    return (0) ;
}

我得到这样的输出:

$ ./prog
CHOLMOD sparse:  A:  18000-by-18000, nz 3457658, upper.  OK
Time: 14570.3950 ms

CHOLMOD GPU/CPU statistics:
SYRK  CPU calls          888 time   1.0637e-01
      GPU calls          213 time   8.9194e-02
GEMM  CPU calls          711 time   1.1511e-01
      GPU calls          213 time   1.9351e-03
POTRF CPU calls          217 time   3.2180e-02
      GPU calls            5 time   1.5788e-01
TRSM  CPU calls          217 time   6.0409e-01
      GPU calls            4 time   5.6943e-02
time in the BLAS: CPU   8.5774e-01 GPU   3.0595e-01 total:   1.1637e+00
assembly time   0.0000e+00    0.0000e+00
$

表示正在使用 GPU。

关于无法在我自己的代码中使用 CHOLMOD 和 CUDA 加速,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32015860/

相关文章:

c - 使用 calloc 和 free 后内存泄漏?

python - Cuda:未找到库 nvvm

c++ - 使用并行归约的 CUDA 矩阵乘法

cuda - 使用非均匀节点优化 CUDA 内核插值

c++ - 索引到 CHOLMOD 密集 vector 数组

c++ - 在 Ubuntu 中编译 SuiteSparse,安装 CHOLMOD 时中断

c - 如果输入的值大于 3,则函数将永远递归运行

c - 在 C 中存储 char* 数组

c - 在多线程环境中两个函数之间共享公共(public)变量

r - R 中的矩阵运算 : parallelization, 稀疏运算,GPU 计算