Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

transpose different matrices in parallel

Tags:

c++

cuda

I have like 3 different size of matrices and want to transpose them parallel.

Firstly I put these in a 2D array using malloc and then use cudaMalloc to transfer array from host(h_B) to device (d_B).

Using threadIdx to find each address of matrix in the array. The cublas function is used. Here are my code.

The code can be compiled but I cannot get result. It seems that in global function float *A = new float[m*n] is not a good way.

Dose anyone have ideas of this? Thanks so much!

/* Includes, system */
#include <stdio.h>
#include <stdlib.h>
#include<iostream>

/* Includes, cuda */
#include <cuda_runtime.h>
#include <cublas_v2.h>

/* Includes, cuda helper functions */
#include <helper_cuda.h>

__global__ void transposeCublasSgeam(int *M_A, int *N_A, float *ptrA, float *ptrC, const int N, int *address)
{
    cublasHandle_t cnpHandle;
    cublasStatus_t status = cublasCreate(&cnpHandle);

    if (status != CUBLAS_STATUS_SUCCESS)
    {
        return;
    }

    const float d_alpha = 1.0f;
    const float d_beta = 0.0f;
    int idx = threadIdx.x;
    if(idx<N){
      int m = M_A[idx]; //A_row
      int n = N_A[idx]; //A_col
      float *A = new float[m*n]; 
      float *C = new float[m*n];
      A = ptrA+address[idx];
      C = ptrC+address[idx];
      cublasSgeam(cnpHandle, CUBLAS_OP_T, CUBLAS_OP_T, m, n, &d_alpha, (const float*)A, n, &d_beta, (const float *)A, n, C, m);
      delete[] A;
      delete[] C;
    }
     cublasDestroy(cnpHandle);

}

int main()
{

    const int N = 3;
    int M_B[N] = { 2,3,2 }; //row number of matrices 
    int N_B[N] = { 3,2,4 }; //col number of matrices 

    float a[6] = { 1,2,3,
                  4,5,6 };
    float b[6] = { 1,2,
                 3,4,
                 5,6};
    float c[8] = { 1,2,3,1,
                  2,3,4,5 };

    float **h_B = (float**)malloc(N * sizeof(float*));
    float **h_BT = (float**)malloc(N * sizeof(float*));

    h_B[0] = a, h_BT[0] = a;
    h_B[1] = b, h_BT[1] = b;
    h_B[2] = c, h_BT[2] = c;

    int NUM_B = 20; // total number of elements
    int address[] = {0,6,12}; 

    float *d_B, *d_BT;
    checkCudaErrors(cudaMalloc((void **)&d_B, NUM_B * sizeof(float)));
    checkCudaErrors(cudaMalloc((void **)&d_BT, NUM_B * sizeof(float)));
    checkCudaErrors(cudaMemcpy(d_B, h_B, NUM_B * sizeof(float), cudaMemcpyHostToDevice));
    checkCudaErrors(cudaMemcpy(d_BT, h_BT, NUM_B * sizeof(float), cudaMemcpyHostToDevice));

    transposeCublasSgeam<<<1,N>>>(M_B, N_B, d_B,d_BT, N,address); 

    checkCudaErrors(cudaMemcpy(h_BT, d_BT, NUM_B * sizeof(float), cudaMemcpyDeviceToHost));

    cudaFree(d_B);
    cudaFree(d_BT);
    delete[] h_B;
    delete[] h_BT;

    return 0;
}

like image 241
Mardha Avatar asked Aug 24 '26 15:08

Mardha


1 Answers

There were a number of errors in your code. I will probably miss some in my description.

  1. Note that this cublas-in-device-code functionality is no longer available in newer CUDA versions.
  2. Every pointer that is passed to device code needs an allocation with cudaMalloc. You had done cudaMalloc for a few pointers, but not all of them.
  3. You're confused about pointers and arrays of pointers. I won't be able to sort all of that out for you. Your kernel design really doesn't need the complexity of using arrays of pointers. So I've removed all that.
  4. In CUDA dynamic parallelism (CDP), pointers to the local address space cannot be passed to child kernels. You can't use alpha and beta in the local address space, and pass pointers to those to CUBLAS in CDP.
  5. To do a pure transpose, study the CUBLAS Sgeam documentation for the recommended parameters to use.

I believe there were other things I fixed. Please study this example:

$ cat t1433.cu
/* Includes, system */
#include <stdio.h>
#include <stdlib.h>
#include<iostream>

/* Includes, cuda */
#include <cuda_runtime.h>
#include <cublas_v2.h>

/* Includes, cuda helper functions */
#include <helper_cuda.h>

__global__ void transposeCublasSgeam(int *M_A, int *N_A, float *ptrA, float *ptrC, const int N, int *address)
{
    cublasHandle_t cnpHandle;
    cublasStatus_t status = cublasCreate(&cnpHandle);

    if (status != CUBLAS_STATUS_SUCCESS)
    {
        printf("thread: %d, error1: %d\n", threadIdx.x, (int)status);
        return;
    }

    float *d_alpha =  new float; // a pointer to device-heap, not local memory
    *d_alpha = 1.0f;
    float *d_beta  = new float;
    *d_beta = 0.0f;
    int idx = threadIdx.x;
    if(idx<N){
      int m = M_A[idx]; //A_row
      int n = N_A[idx]; //A_col
      status = cublasSgeam(cnpHandle, CUBLAS_OP_T, CUBLAS_OP_N, m, n, d_alpha, ptrA+address[idx], n, d_beta, ptrC+address[idx], m, ptrC+address[idx], m);
      if (status != CUBLAS_STATUS_SUCCESS)
      {
        printf("thread: %d, error2: %d\n", threadIdx.x, (int)status);
        return;
      }
    }
     cublasDestroy(cnpHandle);

}

int main()
{

    const int N = 3;
    int M_B[N] = { 2,3,2 }; //row number of matrices
    int N_B[N] = { 3,2,4 }; //col number of matrices

    float a[6] = { 1,2,3,
                  4,5,6 };
    float b[6] = { 1,2,
                 3,4,
                 5,6};
    float c[8] = { 1,2,3,1,
                  2,3,4,5 };
    float *h_Bdata  = (float *)malloc(sizeof(a)+sizeof(b)+sizeof(c));
    float *h_BTdata = (float *)malloc(sizeof(a)+sizeof(b)+sizeof(c));
    memcpy(h_Bdata, a, sizeof(a));
    memcpy(h_Bdata+(sizeof(a)/sizeof(a[0])), b, sizeof(b));
    memcpy(h_Bdata+(sizeof(a)/sizeof(a[0]))+(sizeof(b)/sizeof(b[0])), c, sizeof(c));

    int NUM_B = 20; // total number of elements
    int address[] = {0,6,12};
    int *d_address;
    cudaMalloc(&d_address, sizeof(address));
    cudaMemcpy(d_address, address, sizeof(address), cudaMemcpyHostToDevice);
    int *d_M_B, *d_N_B;
    cudaMalloc(&d_M_B, sizeof(M_B));
    cudaMalloc(&d_N_B, sizeof(N_B));
    cudaMemcpy(d_M_B, M_B, sizeof(M_B), cudaMemcpyHostToDevice);
    cudaMemcpy(d_N_B, N_B, sizeof(N_B), cudaMemcpyHostToDevice);
    float *d_B, *d_BT;
    checkCudaErrors(cudaMalloc((void **)&d_B, NUM_B * sizeof(float)));
    checkCudaErrors(cudaMalloc((void **)&d_BT, NUM_B * sizeof(float)));
    checkCudaErrors(cudaMemcpy(d_B, h_Bdata, NUM_B * sizeof(float), cudaMemcpyHostToDevice));

    transposeCublasSgeam<<<1,N>>>(d_M_B, d_N_B, d_B,d_BT, N,d_address);

    checkCudaErrors(cudaMemcpy(h_BTdata, d_BT, NUM_B * sizeof(float), cudaMemcpyDeviceToHost));
    std::cout << "B , BT" << std::endl;
    for (int i = 0; i < NUM_B; i++){
      std::cout << h_Bdata[i]  << " , " << h_BTdata[i] << std::endl;}
    cudaFree(d_B);
    cudaFree(d_BT);

    return 0;
}
$ /usr/local/cuda-8.0/bin/nvcc -I/usr/local/cuda-8.0/samples/common/inc  t1433.cu -rdc=true -lcublas_device -lcudadevrt -arch=sm_35 -o t1433
$ LD_LIBRARY_PATH=/usr/local/cuda-8.0/lib64 CUDA_VISIBLE_DEVICES="3" cuda-memcheck ./t1433
========= CUDA-MEMCHECK
B , BT
1 , 1
2 , 4
3 , 2
4 , 5
5 , 3
6 , 6
1 , 1
2 , 3
3 , 5
4 , 2
5 , 4
6 , 6
1 , 1
2 , 2
3 , 2
1 , 3
2 , 3
3 , 4
4 , 1
5 , 5
========= ERROR SUMMARY: 0 errors
$
like image 87
Robert Crovella Avatar answered Aug 26 '26 03:08

Robert Crovella



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!