// RUN: %run_test hipify "%s" "%t" %hipify_args %clang_args #include #include #include // CHECK: #include #include // CHECK: #include #include // CHECK: #include #include // NOTE: CUDA 10.0 /* * compute | b - A*x|_inf */ void residaul_eval( int n, const float *ds, const float *dl, const float *d, const float *du, const float *dw, const float *b, const float *x, float *r_nrminf_ptr) { float r_nrminf = 0; for (int i = 0; i < n; i++) { float dot = 0; if (i > 1) { dot += ds[i] * x[i - 2]; } if (i > 0) { dot += dl[i] * x[i - 1]; } dot += d[i] * x[i]; if (i < (n - 1)) { dot += du[i] * x[i + 1]; } if (i < (n - 2)) { dot += dw[i] * x[i + 2]; } float ri = b[i] - dot; r_nrminf = (r_nrminf > fabs(ri)) ? r_nrminf : fabs(ri); } *r_nrminf_ptr = r_nrminf; } int main(int argc, char*argv[]) { // CHECK: hipsparseHandle_t cusparseH = NULL; cusparseHandle_t cusparseH = NULL; // CHECK: hipblasHandle_t cublasH = NULL; cublasHandle_t cublasH = NULL; // CHECK: hipStream_t stream = NULL; cudaStream_t stream = NULL; // CHECK: hipsparseStatus_t status = HIPSPARSE_STATUS_SUCCESS; cusparseStatus_t status = CUSPARSE_STATUS_SUCCESS; // CHECK: hipblasStatus_t cublasStat = HIPBLAS_STATUS_SUCCESS; cublasStatus_t cublasStat = CUBLAS_STATUS_SUCCESS; // CHECK: hipError_t cudaStat1 = hipSuccess; cudaError_t cudaStat1 = cudaSuccess; const int n = 4; const int batchSize = 2; /* * | 1 8 13 0 | | 1 | | -0.0592 | * A1 =| 5 2 9 14 |, b1 = | 2 |, x1 = | 0.3428 | * | 11 6 3 10 | | 3 | | -0.1295 | * | 0 12 7 4 | | 4 | | 0.1982 | * * | 15 22 27 0 | | 5 | | -0.0012 | * A2 =| 19 16 23 28 |, b2 = | 6 |, x2 = | 0.2792 | * | 25 20 17 24 | | 7 | | -0.0416 | * | 0 26 21 18 | | 8 | | 0.0898 | */ /* * A = (ds, dl, d, du, dw), B and X are in aggregate format */ const float ds[n * batchSize] = { 0, 0, 11, 12, 0, 0, 25, 26 }; const float dl[n * batchSize] = { 0, 5, 6, 7, 0, 19, 20, 21 }; const float d[n * batchSize] = { 1, 2, 3, 4, 15, 16, 17, 18 }; const float du[n * batchSize] = { 8, 9, 10, 0, 22, 23, 24, 0 }; const float dw[n * batchSize] = { 13,14, 0, 0, 27, 28, 0, 0 }; const float B[n * batchSize] = { 1, 2, 3, 4, 5, 6, 7, 8 }; float X[n * batchSize]; /* Xj = Aj \ Bj */ /* device memory * (d_ds0, d_dl0, d_d0, d_du0, d_dw0) is aggregate format * (d_ds, d_dl, d_d, d_du, d_dw) is interleaved format */ float *d_ds0 = NULL; float *d_dl0 = NULL; float *d_d0 = NULL; float *d_du0 = NULL; float *d_dw0 = NULL; float *d_ds = NULL; float *d_dl = NULL; float *d_d = NULL; float *d_du = NULL; float *d_dw = NULL; float *d_B = NULL; float *d_X = NULL; size_t lworkInBytes = 0; char *d_work = NULL; const float h_one = 1; const float h_zero = 0; int algo = 0; /* QR factorization */ printf("example of gpsv (interleaved format) \n"); printf("n = %d, batchSize = %d\n", n, batchSize); /* step 1: create cusparse/cublas handle, bind a stream */ // CHECK: cudaStat1 = hipStreamCreateWithFlags(&stream, hipStreamNonBlocking); cudaStat1 = cudaStreamCreateWithFlags(&stream, cudaStreamNonBlocking); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); // CHECK: status = hipsparseCreate(&cusparseH); status = cusparseCreate(&cusparseH); // CHECK: assert(HIPSPARSE_STATUS_SUCCESS == status); assert(CUSPARSE_STATUS_SUCCESS == status); // CHECK: status = hipsparseSetStream(cusparseH, stream); status = cusparseSetStream(cusparseH, stream); // CHECK: assert(HIPSPARSE_STATUS_SUCCESS == status); assert(CUSPARSE_STATUS_SUCCESS == status); // CHECK: cublasStat = hipblasCreate(&cublasH); cublasStat = cublasCreate(&cublasH); // CHECK: assert(HIPBLAS_STATUS_SUCCESS == cublasStat); assert(CUBLAS_STATUS_SUCCESS == cublasStat); // CHECK: cublasStat = hipblasSetStream(cublasH, stream); cublasStat = cublasSetStream(cublasH, stream); // CHECK: assert(HIPBLAS_STATUS_SUCCESS == cublasStat); assert(CUBLAS_STATUS_SUCCESS == cublasStat); /* step 2: allocate device memory */ // CHECK: cudaStat1 = hipMalloc((void**)&d_ds0, sizeof(float)*n*batchSize); cudaStat1 = cudaMalloc((void**)&d_ds0, sizeof(float)*n*batchSize); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); // CHECK: cudaStat1 = hipMalloc((void**)&d_dl0, sizeof(float)*n*batchSize); cudaStat1 = cudaMalloc((void**)&d_dl0, sizeof(float)*n*batchSize); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); // CHECK: cudaStat1 = hipMalloc((void**)&d_d0, sizeof(float)*n*batchSize); cudaStat1 = cudaMalloc((void**)&d_d0, sizeof(float)*n*batchSize); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); // CHECK: cudaStat1 = hipMalloc((void**)&d_du0, sizeof(float)*n*batchSize); cudaStat1 = cudaMalloc((void**)&d_du0, sizeof(float)*n*batchSize); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); // CHECK: cudaStat1 = hipMalloc((void**)&d_dw0, sizeof(float)*n*batchSize); cudaStat1 = cudaMalloc((void**)&d_dw0, sizeof(float)*n*batchSize); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); // CHECK: cudaStat1 = hipMalloc((void**)&d_ds, sizeof(float)*n*batchSize); cudaStat1 = cudaMalloc((void**)&d_ds, sizeof(float)*n*batchSize); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); // CHECK: cudaStat1 = hipMalloc((void**)&d_dl, sizeof(float)*n*batchSize); cudaStat1 = cudaMalloc((void**)&d_dl, sizeof(float)*n*batchSize); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); // CHECK: cudaStat1 = hipMalloc((void**)&d_d, sizeof(float)*n*batchSize); cudaStat1 = cudaMalloc((void**)&d_d, sizeof(float)*n*batchSize); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); // CHECK: cudaStat1 = hipMalloc((void**)&d_du, sizeof(float)*n*batchSize); cudaStat1 = cudaMalloc((void**)&d_du, sizeof(float)*n*batchSize); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); // CHECK: cudaStat1 = hipMalloc((void**)&d_dw, sizeof(float)*n*batchSize); cudaStat1 = cudaMalloc((void**)&d_dw, sizeof(float)*n*batchSize); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); // CHECK: cudaStat1 = hipMalloc((void**)&d_B, sizeof(float)*n*batchSize); cudaStat1 = cudaMalloc((void**)&d_B, sizeof(float)*n*batchSize); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); // CHECK: cudaStat1 = hipMalloc((void**)&d_X, sizeof(float)*n*batchSize); cudaStat1 = cudaMalloc((void**)&d_X, sizeof(float)*n*batchSize); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); /* step 3: prepare data in device, interleaved format */ // CHECK: cudaStat1 = hipMemcpy(d_ds0, ds, sizeof(float)*n*batchSize, hipMemcpyHostToDevice); cudaStat1 = cudaMemcpy(d_ds0, ds, sizeof(float)*n*batchSize, cudaMemcpyHostToDevice); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); // CHECK: cudaStat1 = hipMemcpy(d_dl0, dl, sizeof(float)*n*batchSize, hipMemcpyHostToDevice); cudaStat1 = cudaMemcpy(d_dl0, dl, sizeof(float)*n*batchSize, cudaMemcpyHostToDevice); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); // CHECK: cudaStat1 = hipMemcpy(d_d0, d, sizeof(float)*n*batchSize, hipMemcpyHostToDevice); cudaStat1 = cudaMemcpy(d_d0, d, sizeof(float)*n*batchSize, cudaMemcpyHostToDevice); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); // CHECK: cudaStat1 = hipMemcpy(d_du0, du, sizeof(float)*n*batchSize, hipMemcpyHostToDevice); cudaStat1 = cudaMemcpy(d_du0, du, sizeof(float)*n*batchSize, cudaMemcpyHostToDevice); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); // CHECK: cudaStat1 = hipMemcpy(d_dw0, dw, sizeof(float)*n*batchSize, hipMemcpyHostToDevice); cudaStat1 = cudaMemcpy(d_dw0, dw, sizeof(float)*n*batchSize, cudaMemcpyHostToDevice); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); // CHECK: cudaStat1 = hipMemcpy(d_B, B, sizeof(float)*n*batchSize, hipMemcpyHostToDevice); cudaStat1 = cudaMemcpy(d_B, B, sizeof(float)*n*batchSize, cudaMemcpyHostToDevice); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); // CHECK: hipDeviceSynchronize(); cudaDeviceSynchronize(); /* convert ds to interleaved format * ds = transpose(ds0) */ // CHECK: cublasStat = hipblasSgeam( // CHECK: HIPBLAS_OP_T, // CHECK: HIPBLAS_OP_T, cublasStat = cublasSgeam( cublasH, CUBLAS_OP_T, /* transa */ CUBLAS_OP_T, /* transb, don't care */ batchSize, /* number of rows of ds */ n, /* number of columns of ds */ &h_one, d_ds0, /* ds0 is n-by-batchSize */ n, /* leading dimension of ds0 */ &h_zero, NULL, n, /* don't cae */ d_ds, /* ds is batchSize-by-n */ batchSize); /* leading dimension of ds */ // CHECK: assert(HIPBLAS_STATUS_SUCCESS == cublasStat); assert(CUBLAS_STATUS_SUCCESS == cublasStat); /* convert dl to interleaved format * dl = transpose(dl0) */ // CHECK: cublasStat = hipblasSgeam( // CHECK: HIPBLAS_OP_T, // CHECK: HIPBLAS_OP_T, cublasStat = cublasSgeam( cublasH, CUBLAS_OP_T, /* transa */ CUBLAS_OP_T, /* transb, don't care */ batchSize, /* number of rows of dl */ n, /* number of columns of dl */ &h_one, d_dl0, /* dl0 is n-by-batchSize */ n, /* leading dimension of dl0 */ &h_zero, NULL, n, /* don't cae */ d_dl, /* dl is batchSize-by-n */ batchSize /* leading dimension of dl */ ); // CHECK: assert(HIPBLAS_STATUS_SUCCESS == cublasStat); assert(CUBLAS_STATUS_SUCCESS == cublasStat); /* convert d to interleaved format * d = transpose(d0) */ // CHECK: cublasStat = hipblasSgeam( // CHECK: HIPBLAS_OP_T, // CHECK: HIPBLAS_OP_T, cublasStat = cublasSgeam( cublasH, CUBLAS_OP_T, /* transa */ CUBLAS_OP_T, /* transb, don't care */ batchSize, /* number of rows of d */ n, /* number of columns of d */ &h_one, d_d0, /* d0 is n-by-batchSize */ n, /* leading dimension of d0 */ &h_zero, NULL, n, /* don't cae */ d_d, /* d is batchSize-by-n */ batchSize /* leading dimension of d */ ); // CHECK: assert(HIPBLAS_STATUS_SUCCESS == cublasStat); assert(CUBLAS_STATUS_SUCCESS == cublasStat); /* convert du to interleaved format * du = transpose(du0) */ // CHECK: cublasStat = hipblasSgeam( // CHECK: HIPBLAS_OP_T, // CHECK: HIPBLAS_OP_T, cublasStat = cublasSgeam( cublasH, CUBLAS_OP_T, /* transa */ CUBLAS_OP_T, /* transb, don't care */ batchSize, /* number of rows of du */ n, /* number of columns of du */ &h_one, d_du0, /* du0 is n-by-batchSize */ n, /* leading dimension of du0 */ &h_zero, NULL, n, /* don't cae */ d_du, /* du is batchSize-by-n */ batchSize /* leading dimension of du */ ); // CHECK: assert(HIPBLAS_STATUS_SUCCESS == cublasStat); assert(CUBLAS_STATUS_SUCCESS == cublasStat); /* convert dw to interleaved format * dw = transpose(dw0) */ // CHECK: cublasStat = hipblasSgeam( // CHECK: HIPBLAS_OP_T, // CHECK: HIPBLAS_OP_T, cublasStat = cublasSgeam( cublasH, CUBLAS_OP_T, /* transa */ CUBLAS_OP_T, /* transb, don't care */ batchSize, /* number of rows of dw */ n, /* number of columns of dw */ &h_one, d_dw0, /* dw0 is n-by-batchSize */ n, /* leading dimension of dw0 */ &h_zero, NULL, n, /* don't cae */ d_dw, /* dw is batchSize-by-n */ batchSize /* leading dimension of dw */ ); // CHECK: assert(HIPBLAS_STATUS_SUCCESS == cublasStat); assert(CUBLAS_STATUS_SUCCESS == cublasStat); /* convert B to interleaved format * X = transpose(B) */ // CHECK: cublasStat = hipblasSgeam( // CHECK: HIPBLAS_OP_T, // CHECK: HIPBLAS_OP_T, cublasStat = cublasSgeam( cublasH, CUBLAS_OP_T, /* transa */ CUBLAS_OP_T, /* transb, don't care */ batchSize, /* number of rows of X */ n, /* number of columns of X */ &h_one, d_B, /* B is n-by-batchSize */ n, /* leading dimension of B */ &h_zero, NULL, n, /* don't cae */ d_X, /* X is batchSize-by-n */ batchSize /* leading dimension of X */ ); // CHECK: assert(HIPBLAS_STATUS_SUCCESS == cublasStat); assert(CUBLAS_STATUS_SUCCESS == cublasStat); /* step 4: prepare workspace */ // NOTE: CUDA 10.0 // TODO: status = hipsparseSgpsvInterleavedBatch_bufferSizeExt( status = cusparseSgpsvInterleavedBatch_bufferSizeExt( cusparseH, algo, n, d_ds, d_dl, d_d, d_du, d_dw, d_X, batchSize, &lworkInBytes); // CHECK: assert(HIPSPARSE_STATUS_SUCCESS == status); assert(CUSPARSE_STATUS_SUCCESS == status); printf("lworkInBytes = %lld \n", (long long)lworkInBytes); // CHECK: cudaStat1 = hipMalloc((void**)&d_work, lworkInBytes); cudaStat1 = cudaMalloc((void**)&d_work, lworkInBytes); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); /* step 5: solve Aj*xj = bj */ // NOTE: CUDA 10.0 // TODO: status = hipsparseSgpsvInterleavedBatch( status = cusparseSgpsvInterleavedBatch( cusparseH, algo, n, d_ds, d_dl, d_d, d_du, d_dw, d_X, batchSize, d_work); // CHECK: cudaStat1 = hipDeviceSynchronize(); cudaStat1 = cudaDeviceSynchronize(); // CHECK: assert(HIPSPARSE_STATUS_SUCCESS == status); assert(CUSPARSE_STATUS_SUCCESS == status); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); /* step 6: convert X back to aggregate format */ /* B = transpose(X) */ // CHECK: cublasStat = hipblasSgeam( // CHECK: HIPBLAS_OP_T, // CHECK: HIPBLAS_OP_T, cublasStat = cublasSgeam( cublasH, CUBLAS_OP_T, /* transa */ CUBLAS_OP_T, /* transb, don't care */ n, /* number of rows of B */ batchSize, /* number of columns of B */ &h_one, d_X, /* X is batchSize-by-n */ batchSize, /* leading dimension of X */ &h_zero, NULL, n, /* don't cae */ d_B, /* B is n-by-batchSize */ n /* leading dimension of B */ ); // CHECK: assert(HIPBLAS_STATUS_SUCCESS == cublasStat); assert(CUBLAS_STATUS_SUCCESS == cublasStat); // CHECK: hipDeviceSynchronize(); cudaDeviceSynchronize(); /* step 7: residual evaluation */ // CHECK: cudaStat1 = hipMemcpy(X, d_B, sizeof(float)*n*batchSize, hipMemcpyDeviceToHost); cudaStat1 = cudaMemcpy(X, d_B, sizeof(float)*n*batchSize, cudaMemcpyDeviceToHost); // CHECK: assert(hipSuccess == cudaStat1); assert(cudaSuccess == cudaStat1); // CHECK: hipDeviceSynchronize(); cudaDeviceSynchronize(); printf("==== x1 = inv(A1)*b1 \n"); for (int j = 0; j < n; j++) { printf("x1[%d] = %f\n", j, X[j]); } float r1_nrminf; residaul_eval( n, ds, dl, d, du, dw, B, X, &r1_nrminf ); printf("|b1 - A1*x1| = %E\n", r1_nrminf); printf("\n==== x2 = inv(A2)*b2 \n"); for (int j = 0; j < n; j++) { printf("x2[%d] = %f\n", j, X[n + j]); } float r2_nrminf; residaul_eval( n, ds + n, dl + n, d + n, du + n, dw + n, B + n, X + n, &r2_nrminf ); printf("|b2 - A2*x2| = %E\n", r2_nrminf); /* free resources */ // CHECK: if (d_ds0) hipFree(d_ds0); if (d_ds0) cudaFree(d_ds0); // CHECK: if (d_dl0) hipFree(d_dl0); if (d_dl0) cudaFree(d_dl0); // CHECK: if (d_d0) hipFree(d_d0); if (d_d0) cudaFree(d_d0); // CHECK: if (d_du0) hipFree(d_du0); if (d_du0) cudaFree(d_du0); // CHECK: if (d_dw0) hipFree(d_dw0); if (d_dw0) cudaFree(d_dw0); // CHECK: if (d_ds) hipFree(d_ds); if (d_ds) cudaFree(d_ds); // CHECK: if (d_dl) hipFree(d_dl); if (d_dl) cudaFree(d_dl); // CHECK: if (d_d) hipFree(d_d); if (d_d) cudaFree(d_d); // CHECK: if (d_du) hipFree(d_du); if (d_du) cudaFree(d_du); // CHECK: if (d_dw) hipFree(d_dw); if (d_dw) cudaFree(d_dw); // CHECK: if (d_B) hipFree(d_B); if (d_B) cudaFree(d_B); // CHECK: if (d_X) hipFree(d_X); if (d_X) cudaFree(d_X); // CHECK: if (cusparseH) hipsparseDestroy(cusparseH); if (cusparseH) cusparseDestroy(cusparseH); // CHECK: if (cublasH) hipblasDestroy(cublasH); if (cublasH) cublasDestroy(cublasH); // CHECK: if (stream) hipStreamDestroy(stream); if (stream) cudaStreamDestroy(stream); // CHECK: hipDeviceReset(); cudaDeviceReset(); return 0; }