分析 cusolverDnSgeqrf 的具体算法

1. 分析实例

源码:

#include<time.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<cuda_runtime.h>
#include<cublas_v2.h>
#include<cusolverDn.h>
#define BILLION 1000000000L;

void print_vector(float* tau, int n){
    for(int i=0; i<n; i++)
        printf("%7.4f ", tau[i]);
}

void print_matrix(float* A, int m, int n, int lda){
    for(int i=0; i<m; i++)    {
        for(int j=0; j<n; j++){
            printf("%7.4f, ", A[i + j*lda]);
        }
        printf("\n");
    }
}

void init_matrix(float* A, int m, int n, int lda, int seed){
    srand(seed);

    for(int j=0; j<n; j++)    {
        for(int i=0; i<m; i++){
            A[i + j*lda] = (rand()%1000)/750.0f;
        }
    }
}

void tau_matrix(float* A, int m, int n, int lda)
{
    printf("\ntuu = ");
    for(int j=0; j<n-1; j++){
        float tau, dot;

        tau = 0.0f;
        dot = 0.0f;
        for(int i=j+1; i<m; i++){
            dot += A[i + j*lda]*A[i + j*lda];
        }
        dot += 1.0f;
        tau = 2.0f/dot;
        printf("%7.4f ", tau);
    }
}

int main(int argc, char *argv[]){

    struct timespec start, stop; // variables for timing
    double accum;                // elapsed time variable
    cusolverDnHandle_t cusolverH;
    cublasHandle_t cublasH;
    cublasStatus_t cublas_status = CUBLAS_STATUS_SUCCESS;
    cusolverStatus_t cusolver_status = CUSOLVER_STATUS_SUCCESS;
    cudaError_t cudaStat = cudaSuccess;
    const int m = 7;//8192; // number of rows of A
    const int n = 7;//8192; // number of columns of A
    const int lda = m;  // leading dimension of A
    // declare matrices A and Q,R on the host
    float *A, *Q, *R;

    // prepare host memeory
    A = (float *)malloc(lda * n * sizeof(float)); // matr . A on the host
    Q = (float *)malloc(lda * n * sizeof(float)); // orthogonal factor Q
    R = (float *)malloc(n * n * sizeof(float));   // R=I-Q^T*Q

    init_matrix(A, m, n, lda, 2003);

    float *d_A, *d_R;                    // matrices A, R on the device
    float *d_tau;                        // scalars defining the elementary reflectors
    int *devInfo;                        // info on the device
    float *d_work;                       // workspace on the device
    // workspace sizes
    int lwork_geqrf = 0;
    int lwork_orgqr = 0;
    int lwork = 0;
    int info_gpu = 0;             // info copied from the device
    const float h_one = 1;        // constants used in
    const float h_minus_one = -1; // computations of I-Q^T*Q
    // create cusolver and cublas handles
    cusolver_status = cusolverDnCreate(&cusolverH);
    cublas_status = cublasCreate(&cublasH);
    // prepare device memory
    cudaStat = cudaMalloc((void **)&d_A, sizeof(float) * lda * n);
    cudaStat = cudaMalloc((void **)&d_tau, sizeof(float) * n);
    cudaStat = cudaMalloc((void **)&devInfo, sizeof(int));
    cudaStat = cudaMalloc((void **)&d_R, sizeof(float) * n * n);
    cudaStat = cudaMemcpy(d_A, A, sizeof(float) * lda * n,
                          cudaMemcpyHostToDevice); // copy d_A <- A
    // compute working space for geqrf and orgqr
    cusolver_status = cusolverDnSgeqrf_bufferSize(cusolverH,
                                                  m, n, d_A, lda, &lwork_geqrf); // compute Sgeqrf buffer size
    cusolver_status = cusolverDnSorgqr_bufferSize(cusolverH,
                                                  m, n, n, d_A, lda, d_tau, &lwork_orgqr); // and Sorgqr b. size
    lwork = (lwork_geqrf > lwork_orgqr) ? lwork_geqrf : lwork_orgqr;
    // device memory for workspace
    cudaStat = cudaMalloc((void **)&d_work, sizeof(float) * lwork);
    // QR factorization for d_A
    clock_gettime(CLOCK_REALTIME, &start); // start timer
    cusolver_status = cusolverDnSgeqrf(cusolverH, m, n, d_A, lda,
                                       d_tau, d_work, lwork, devInfo);
    cudaStat = cudaDeviceSynchronize();
    clock_gettime(CLOCK_REALTIME, &stop);  // stop timer
    accum = (stop.tv_sec - start.tv_sec) + // elapsed time
            (stop.tv_nsec - start.tv_nsec) / (double)BILLION;
    printf(" Sgeqrf time : %lf sec .\n", accum); // print elapsed time
    cudaStat = cudaMemcpy(&info_gpu, devInfo, sizeof(int),
                          cudaMemcpyDeviceToHost); // copy devInfo -> info_gpu
    // check geqrf error code
    printf("\n after geqrf : info_gpu = %d\n", info_gpu);
///
    printf("\nA =\n");print_matrix(A, m, n, lda);
    cudaStat = cudaMemcpy(A, d_A, sizeof(float) * lda * n,
                          cudaMemcpyDeviceToHost);
    printf("\nV+R-I =\n");print_matrix(A, m, n, lda);

    float* tau = nullptr;

    tau = (float*)malloc(n*sizeof(float));
    cudaStat = cudaMemcpy(tau, d_tau, n*sizeof(float), cudaMemcpyDeviceToHost);
    printf("\ntau = ");print_vector(tau, n);


    tau_matrix(A, m, n, lda);

    free(tau);
///
    // apply orgqr function to compute the orthogonal matrix Q
    // using elementary reflectors vectors stored in d_A and
    // elementary reflectors scalars stored in d_tau ,
    cusolver_status = cusolverDnSorgqr(cusolverH, m, n, n, d_A,
                                       lda, d_tau, d_work, lwork, devInfo);
    cudaStat = cudaDeviceSynchronize();
    cudaStat = cudaMemcpy(&info_gpu, devInfo, sizeof(int),
                          cudaMemcpyDeviceToHost); // copy devInfo -> info_gpu
    // check orgqr error code
    printf("\n after orgqr : info_gpu = %d\n", info_gpu);
    cudaStat = cudaMemcpy(Q, d_A, sizeof(float) * lda * n,
                          cudaMemcpyDeviceToHost); // copy d_A ->Q
    memset(R, 0, sizeof(double) * n * n);          // nxn matrix of zeros
    for (int j = 0; j < n; j++)
    {
        R[j + n * j] = 1.0f; // ones on the diagonal
    }
    cudaStat = cudaMemcpy(d_R, R, sizeof(float) * n * n,
                          cudaMemcpyHostToDevice); // copy R-> d_R
    // compute R = -Q**T*Q + I
    cublas_status = cublasSgemm_v2(cublasH, CUBLAS_OP_T, CUBLAS_OP_N,
                                   n, n, m, &h_minus_one, d_A, lda, d_A, lda, &h_one, d_R, n);
    float dR_nrm2 = 0.0; // norm value
    // compute the norm of R = -Q**T*Q + I
    cublas_status = cublasSnrm2_v2(cublasH, n * n, d_R, 1, &dR_nrm2);
    printf("||I - Q^T*Q|| = %E\n", dR_nrm2); // print the norm
    // free memory
    cudaFree(d_A);
    cudaFree(d_tau);
    cudaFree(devInfo);
    cudaFree(d_work);
    cudaFree(d_R);
    cublasDestroy(cublasH);
    cusolverDnDestroy(cusolverH);
    cudaDeviceReset();
    return 0;
}
// Sqeqrf time : 0.434779 sec .
// after geqrf : info_gpu = 0
// after orgqr : info_gpu = 0
//|I - Q**T*Q| = 2.515004E -04
//
//

Makefile:

TARGETS = qr_cusolver_sgeqrf
all: $(TARGETS)

LD_FLAGS = -L/usr/local/cuda/lib64  	\
	   -lcudart -lcudadevrt 	\
	   -lcusolver -lcublas 		\
	   -lcublasLt -lpthread		


%: %.cpp
	g++ -o $@ $< -I/usr/local/cuda/include  $(LD_FLAGS) -fopenmp -I./cblas_source -L./cblas_source/CBLAS/lib -lcblas_LINUX -L/usr/local/lib -lblas -lgfortran

.PHONY:clean
clean:
	-rm -f $(TARGETS)

2. 运行

 

可知 tau的计算公式如代码中所示。 

相关推荐

  1. 需求工程、需求分析具体方式以及实践

    2024-02-05 06:40:01       17 阅读
  2. 小程序分包加载具体流程

    2024-02-05 06:40:01       41 阅读
  3. RNN具体实现

    2024-02-05 06:40:01       34 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-02-05 06:40:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-02-05 06:40:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-02-05 06:40:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-02-05 06:40:01       20 阅读

热门阅读

  1. iOS 后台任务总结

    2024-02-05 06:40:01       27 阅读
  2. ubuntu 没有屏幕安装QT(SSH远程登陆下)

    2024-02-05 06:40:01       35 阅读
  3. python将Excel文档转成.db数据库文件

    2024-02-05 06:40:01       38 阅读
  4. MySQL 表的增删改查(基础)

    2024-02-05 06:40:01       31 阅读
  5. springboot jar包编写启动start.sh

    2024-02-05 06:40:01       31 阅读
  6. 2024 高级前端面试题之 前端安全模块 「精选篇」

    2024-02-05 06:40:01       40 阅读