É possível enviar dados para a memória GPU que é definido como União, de JCuda?

SonOfSun:

Tenho definido um novo tipo de dados como este no lado GPU (CUDA):

typedef union {
    int i;
    double d;
    long l;
    char s[16];
} data_unit;

data_unit *d_array;

E em Java, temos um conjunto de um dos tipos disponíveis na união definido. Normalmente, podemos fazer o seguinte em Java (JCuda) se temos uma matriz do tipo int por exemplo:

import static jcuda.driver.JCudaDriver.*;


int data_size;
CUdeviceptr d_array;
int[] h_array = new int[data_size];

cuMemAlloc(d_array, data_size * Sizeof.INT);
cuMemcpyHtoD(d_array, Pointer.to(h_array), data_size * Sizeof.INT);

Mas como isso pode ser feito se houver um conjunto de dispositivo que seu tipo é a nossa união? (Supor que ainda o h_array é do tipo int)

int data_size;
CUdeviceptr d_array;
int[] h_array = new int[data_size];

cuMemAlloc(d_array, data_size * Sizeof.?);
// Here we should have some type of alignment (?)
cuMemcpyHtoD(d_array, Pointer.to(h_array), data_size * Sizeof.?);
whn:

Eu acredito que há um mal-entendido fundamental do que uma união é.

Vamos pensar sobre isso. O que torna uma pessoa diferente união de um struct? Ele pode armazenar diferentes tipos de dados em momentos diferentes.

Como ele se realizar esta façanha? Bem pode-se usar algum tipo de variável separada para dinamicamente especificar o tipo ou a quantidade de memória que ocupa, mas não a União não fizer isso, ele conta com o programador saber exatamente o tipo que deseja recuperar e quando. Assim, a única alternativa, se o tipo só é realmente conhecido pelo programador em qualquer ponto no tempo, é simplesmente certificar-se de que existe espaço suficiente alocado para a variável de união que sempre se pode usá-lo para que seja o tipo.

Na verdade, é isso que a união faz, veja aqui (sim, eu sei que é C / C ++, mas isso também se aplica a CUDA também). O que isso significa para você? Isso significa que o tamanho de sua matriz união deve ser o tamanho de seu principal membro x o número de elementos, como o tamanho de uma união é o tamanho de seu principal membro.

Vamos olhar para o seu sindicato para ver como descobrir isso.

typedef union {
    int i;
    double d;
    long l;
    char s[16];
} data_unit;

Seu sindicato tem:

  • int i, Que supomos ser 4 bytes
  • double d, Que é de 8 bytes
  • long l, O que é confuso, porque dependendo do compilador / plataforma pode ser 4 ou 8 bytes, assumimos 8 bytes para agora.
  • char s[16], fácil, 16 bytes

Assim, o maior número de bytes qualquer membro ocupa é a sua char s[16]variável, 16 bytes. Isso significa que você terá que alterar seu código para:

int data_size;
int union_size = 16;
CUdeviceptr d_array;
// copying this to the device will not result in what you expect with out over allocating
// if you just copy over integers, which occupy 4 bytes each, your integers will fill less space than the number of unions 
//  we need to make sure that there is a "stride" here if we want to actually copy real data from host to device. 
// union_size / Sizeof.INT = 4, so there will be 4 x as many ints, 4 for each union. 
int[] h_array = new int[data_size * (union_size / Sizeof.INT)];


// here we aren't looking for size of int to allocate, but the size of our union. 
cuMemAlloc(d_array, data_size * union_size);
// we are copying, again, data_size * union_size bytes
cuMemcpyHtoD(d_array, Pointer.to(h_array), data_size * union_size);

NOTA

Se você deseja copiar ints longo, isso basicamente significa que você terá de atribuir a cada 4 int à int real que você deseja para esse índice.

int 0 é h_array[0], int 1 é h_array[4]int 2 é h_array[8]int n é h_array[n * 4]etc ..

Acho que você gosta

Origin http://43.154.161.224:23101/article/api/json?id=231774&siteId=1
Recomendado
Clasificación