CUDA вызов kernel в цикле

93
15 февраля 2022, 12:50

Стоит задача, нужно вызывать ядро в цикле, но после первой итерации скалярное произведение начинает считать неправильно. Ядро:

__global__ void scaMult_g(float* a, float* b, float* c, float* sum, int n)
{
    int tid = threadIdx.x;
    if (tid > n - 1) return;
    c[tid] = a[tid] * b[tid];
    atomicAdd(sum, c[tid]);
}

Вызов:

for (int i = 0, k = 0; i < usersNum; i++)
    {
        if (i == targetUser)
            continue;
        float* host_b = new float[productsNum];
        for (int j = i * productsNum; j < i * productsNum + productsNum; j++, k++)
        {
            host_b[k] = A[j];
            cout << host_b[k] << "  ";
        }
        cout << endl;
        //calling device to count Cosine measure
#pragma region __device__
        float* dev_c, *dev_sum, *dev_a, *dev_b, host_sum;
        float* sum = 0;
        cudaMalloc((void**)&dev_sum, sizeof(float));
        cudaMalloc((void**)&dev_c, productsNum * sizeof(float));
        cudaMalloc((void**)&dev_a, productsNum * sizeof(float));
        cudaMalloc((void**)&dev_b, productsNum * sizeof(float));
        cudaMemcpy(dev_sum, sum, sizeof(float), cudaMemcpyHostToDevice);
        cudaMemcpy(dev_a, host_a, productsNum * sizeof(float), cudaMemcpyHostToDevice);
        cudaMemcpy(dev_b, host_b, productsNum * sizeof(float), cudaMemcpyHostToDevice);
        scaMult_g << < 1, THREAD_SIZE >> > (dev_a, dev_b, dev_c, dev_sum, productsNum);
        cudaMemcpy(&host_sum, dev_sum, sizeof(float), cudaMemcpyDeviceToHost);
        printf("GPU <a,b>=%f \n", host_sum);
        cout << "Scalar mult between 2 vec: " << host_sum << endl << endl;
        /*cudaFree(dev_c);
        cudaFree(dev_a);
        cudaFree(dev_b);*/
        cudaFree(dev_sum);
        //free(host_b);
        //free(sum);
#pragma endregion
    }
    cout << endl;

Вопрос стоит в том, что именно неправильно написано, что счет происходит неверный? Нужно ли после каждой итерации и вызова ядра очищать память на ядре и на хосте и что именно нужно очищать после вызова?

В консоли результат выдает следующий:

Заранее, спасибо за помощь!

Answer 1

Ошибка как всегда оказалась весьма глупой, mybad В общем из того, что в итоге имею: - после вызова ядра на цпу приписал: cudaDeviceSynchronize();, так как есть вероятность того, что после завершения цикла на цпу и снова вызова ядра не все нити вернулись из гпу - этого делать в данном случае не нужно, но добавил на девайсе __syncthreads();. Но у меня происходит атомарное сложение, посему это не нужно - Ну и ошибка заключалась в том, что итератор kне обнулялся в конце цикла

READ ALSO
Переместить или скопировать элемент jquery

Переместить или скопировать элемент jquery

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

92
Метод Random.setSeed()

Метод Random.setSeed()

Здраствуйте скажите прошу детально что делает метод setSeed() с класса Random в java, какое отношение он имеет к атомарности и почему он synchronizedЗаранее...

119
что такое представления в java android?

что такое представления в java android?

Смотрел видео о разработке под Android и услышал такую фразу "LayoutInflater - класс, который позволяет из xml файлов создавать новые представления",...

65
Исчезают переносы строк при переходе в Gmail через Intent на Samsung

Исчезают переносы строк при переходе в Gmail через Intent на Samsung

Использую intent для перехода из приложения на почту и заполнение письма шаблоном

104