CUDA: копия структуры, содержащей двойной указатель [duplicate]

Я долго искал это решение, Atlast нашел его. Прежде всего объявите все объекты в файле SecondViewController.h, например

@interface SecondViewController: UIviewController 
{
    NSMutableArray *myAray;
    CustomObject *object;
}

Теперь в вашем файле реализации выделите память для этих объектов, таких как

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
     if (self) 
     {
         // Custom initialization
         myAray=[[NSMutableArray alloc] init];
         object=[[CustomObject alloc] init];
     }
     return self;
}

Теперь у вас есть выделил память для Array и объекта. теперь вы можете заполнить эту память, прежде чем нажимать ViewController

. Перейдите к вашему SecondViewController.h и напишите два метода

-(void)setMyArray:(NSArray *)_myArray;
-(void)setMyObject:(CustomObject *)_myObject;

в файле реализации, вы можете реализовать функцию

-(void)setMyArray:(NSArray *)_myArray
{
     [myArra addObjectsFromArray:_myArray];
}
-(void)setMyObject:(CustomObject *)_myObject
{
     [object setCustomObject:_myObject];
}

, ожидая, что ваш CustomObject должен иметь с ним функцию setter.

теперь выполняется ваша основная работа. перейдите к месту, где вы хотите нажать SecondViewController и выполните следующие действия

SecondViewController *secondView= [[SecondViewController alloc] initWithNibName:@"SecondViewController " bundle:[NSBundle MainBundle]] ;
[secondView setMyArray:ArrayToPass];
[secondView setMyObject:objectToPass];
[self.navigationController pushViewController:secondView animated:YES ];

Позаботьтесь о орфографических ошибках.

25
задан Guru Swaroop 31 August 2015 в 03:46
поделиться

3 ответа

Изменить: CUDA 6 представляет Unified Memory, что значительно облегчает эту проблему с «глубокой копией». См. этот пост для более подробной информации.


Не забывайте, что вы можете передавать структуры по значению ядрам. Этот код работает:

// pass struct by value (may not be efficient for complex structures)
__global__ void kernel2(StructA in)
{
    in.arr[threadIdx.x] *= 2;
}

Выполнение этого означает, что вам нужно только скопировать массив на устройство, а не в структуру:

int h_arr[N] = {1,2,3,4,5,6,7,8,9,10};
StructA h_a;
int *d_arr;

// 1. Allocate device array.
cudaMalloc((void**) &(d_arr), sizeof(int)*N);

// 2. Copy array contents from host to device.
cudaMemcpy(d_arr, h_arr, sizeof(int)*N, cudaMemcpyHostToDevice);

// 3. Point to device pointer in host struct.
h_a.arr = d_arr;

// 4. Call kernel with host struct as argument
kernel2<<<N,1>>>(h_a);

// 5. Copy pointer from device to host.
cudaMemcpy(h_arr, d_arr, sizeof(int)*N, cudaMemcpyDeviceToHost);

// 6. Point to host pointer in host struct 
//    (or do something else with it if this is not needed)
h_a.arr = h_arr;
23
ответ дан harrism 23 August 2018 в 18:03
поделиться

Как отметил Марк Харрис, структуры могут передаваться значениями в ядра CUDA. Тем не менее, следует позаботиться о создании надлежащего деструктора, так как деструктор вызывается при выходе из ядра.

Рассмотрим следующий пример

#include <stdio.h>

#include "Utilities.cuh"

#define NUMBLOCKS  512
#define NUMTHREADS 512 * 2

/***************/
/* TEST STRUCT */
/***************/
struct Lock {

    int *d_state;

    // --- Constructor
    Lock(void) {
        int h_state = 0;                                        // --- Host side lock state initializer
        gpuErrchk(cudaMalloc((void **)&d_state, sizeof(int)));  // --- Allocate device side lock state
        gpuErrchk(cudaMemcpy(d_state, &h_state, sizeof(int), cudaMemcpyHostToDevice)); // --- Initialize device side lock state
    }

    // --- Destructor (wrong version)
    //~Lock(void) { 
    //  printf("Calling destructor\n");
    //  gpuErrchk(cudaFree(d_state)); 
    //}

    // --- Destructor (correct version)
//  __host__ __device__ ~Lock(void) {
//#if !defined(__CUDACC__)
//      gpuErrchk(cudaFree(d_state));
//#else
//
//#endif
//  }

    // --- Lock function
    __device__ void lock(void) { while (atomicCAS(d_state, 0, 1) != 0); }

    // --- Unlock function
    __device__ void unlock(void) { atomicExch(d_state, 0); }
};

/**********************************/
/* BLOCK COUNTER KERNEL WITH LOCK */
/**********************************/
__global__ void blockCounterLocked(Lock lock, int *nblocks) {

    if (threadIdx.x == 0) {
        lock.lock();
        *nblocks = *nblocks + 1;
        lock.unlock();
    }
}

/********/
/* MAIN */
/********/
int main(){

    int h_counting, *d_counting;
    Lock lock;

    gpuErrchk(cudaMalloc(&d_counting, sizeof(int)));

    // --- Locked case
    h_counting = 0;
    gpuErrchk(cudaMemcpy(d_counting, &h_counting, sizeof(int), cudaMemcpyHostToDevice));

    blockCounterLocked << <NUMBLOCKS, NUMTHREADS >> >(lock, d_counting);
    gpuErrchk(cudaPeekAtLastError());
    gpuErrchk(cudaDeviceSynchronize());

    gpuErrchk(cudaMemcpy(&h_counting, d_counting, sizeof(int), cudaMemcpyDeviceToHost));
    printf("Counting in the locked case: %i\n", h_counting);

    gpuErrchk(cudaFree(d_counting));
}

с несанкционированным деструктором ( не обращайте слишком много внимания на то, что на самом деле делает код). Если вы запустите этот код, вы получите следующий вывод

Calling destructor
Counting in the locked case: 512
Calling destructor
GPUassert: invalid device pointer D:/Project/passStructToKernel/passClassToKernel/Utilities.cu 37

. Затем два дроидатора вызывают два раза, один раз на выходе ядра и один раз на главном выходе. Сообщение об ошибке связано с тем, что, если ячейки памяти, на которые указывает d_state, освобождаются при выходе ядра, они больше не могут быть освобождены на основном выходе. Соответственно, деструктор должен отличаться для исполнения хоста и устройства. Это выполняется комментарием деструктора в приведенном выше коде.

2
ответ дан JackOLantern 23 August 2018 в 18:03
поделиться

Структура массивов - это кошмар в cuda. Вам придется скопировать каждый указатель на новую структуру, которую устройство может использовать. Может быть, вы могли бы использовать массив структур? Если не единственный способ, который я нашел, это атаковать его так, как вы делаете, что совсем не так.

РЕДАКТИРОВАТЬ: поскольку я не могу комментировать верхнюю запись: Шаг 9 избыточен, так как вы можете изменить шаги 8 и 9 на

// 8. Copy pointer from device to host.
cudaMemcpy(h->arr, d_arr, sizeof(int)*N, cudaMemcpyDeviceToHost);
-3
ответ дан martiert 23 August 2018 в 18:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: