CUDA cudaMemcpy: неверный аргумент

Вот мой код:

struct S {
    int a, b;
    float c, d;
};
class A {
private:
    S* d;
    S h[3];
public:
    A() {
        cutilSafeCall(cudaMalloc((void**)&d, sizeof(S)*3));
    }
void Init();
};

void A::Init() {
    for (int i=0;i<3;i++) {
        h[i].a = 0;
        h[i].b = 1;
        h[i].c = 2;
        h[i].d = 3;
    }
    cutilSafeCall(cudaMemcpy(d, h, 3*sizeof(S), cudaMemcpyHostToDevice));
}

A a;

На самом деле это сложная программа, содержащая CUDA и OpenGL. Когда я отлаживаю эту программу, она терпит неудачу при запуске cudaMemcpy с информацией об ошибке

cudaSafeCall() Ошибка API среды выполнения 11: недопустимый аргумент.

На самом деле эта программа преобразована из другой, которая может работать корректно. Но в этом случае я использовал две переменные S* d и Sh[3] в основной функции, а не в классе. Что еще более странно, так это то, что я реализую этот класс A в небольшой программе, и он отлично работает. И я обновил свой драйвер, ошибка все еще существует.

Может ли кто-нибудь подсказать, почему это происходит и как это решить. Спасибо.


person TonyLic    schedule 14.05.2012    source источник
comment
Кстати, cudaMemcpy вернет cudaErrorInvalidValue.   -  person TonyLic    schedule 14.05.2012
comment
Где находится линия A a;? Это внутри функции или глобально? Если он глобальный, то конструктор может быть вызван до того, как у вас будет действительный контекст устройства (я не уверен в этом, но это возможно). Если это так, то указатель d, переданный cudaMemcpy, будет недействительным.   -  person harrism    schedule 29.05.2012
comment
Можете ли вы опубликовать свою конфигурацию CUDA, которую вы используете, пожалуйста? Я не могу воспроизвести вашу ошибку на старой версии GeForce 9400m и CUDA 5.0.   -  person jopasserat    schedule 15.06.2012


Ответы (1)


Поскольку операции с памятью в CUDA блокируются, они создают точку синхронизации. Таким образом, другие ошибки, если их не проверить с помощью cudaThreadSynchonize, будут выглядеть как ошибки при вызовах памяти.

Поэтому, если при операции с памятью получена ошибка, попробуйте поставить перед ней cudaThreadSynchronize и проверить результат.


Убедитесь, что выполняется первый оператор malloc. Если это проблема инициализации CUDA, как указывает @Harrism, то в этом утверждении произойдет сбой ?? Попробуйте разместить операторы printf и убедитесь, что выполняются правильные инициализации. Я думаю, что обычно ошибки недопустимого аргумента генерируются из-за использования неинициализированных областей памяти.

  1. Напишите printf в свой конструктор, показывающий адрес области памяти cudaMalloc.

    A()
    {
        d = NULL;
        cutilSafeCall(cudaMalloc((void**)&d, sizeof(S)*3));
        printf("D: %p\n", d);
    }
    
  2. Попробуйте сделать копию памяти для области, которая выделена локально, а именно переместите cudaMalloc выше cudaMemcopy (просто для тестирования).

    void A::Init()
    {
        for (int i=0;i<3;i++)
        {
            h[i].a = 0;
            h[i].b = 1;
            h[i].c = 2;
            h[i].d = 3;
        }
        cutilSafeCall(cudaMalloc((void**)&d, sizeof(S)*3)); // here!..
        cutilSafeCall(cudaMemcpy(d, h, 3*sizeof(S), cudaMemcpyHostToDevice));
    }
    

Удачи.

person phoad    schedule 28.08.2012