Различные результаты от CuBlas

Я реализовал следующий код CUDA, но я немного запутался в поведении.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <cuda_runtime.h>
#include "cublas_v2.h"#include <ctime>
#include <chrono>
#include <string>

#define IDX2F(i,j,ld) ((((j)-1)*(ld))+((i)-1))

void PrintMatrix(float* a, int n)
{
int j, i;
for (j = 1; j <= n; j++)
{
for (i = 1; i <= n; i++)
{
printf("%7.0f", a[IDX2F(i, j, n)]);
}
printf("\n");
}
}

float* CreateMatrix(int n)
{
float* matrix = static_cast<float *>(malloc(n * n * sizeof(float)));
if (!matrix)
{
printf("host memory allocation failed");
return nullptr;
}

for (int j = 1; j <= n; j++)
{
for (int i = 1; i <= n; i++)
{
matrix[IDX2F(i, j, n)] = 2;
}
}

return matrix;
}

long CudaMatrixMultiply(float* matrix, int n)
{
cudaError_t cudaStat;
cublasStatus_t status;
cublasHandle_t handle;
float* deviceMatrix;

cudaStat = cudaMalloc(reinterpret_cast<void**>(&deviceMatrix), n * n * sizeof(float));
if (cudaStat != cudaSuccess)
{
printf("device memory allocation failed");
return EXIT_FAILURE;
}

status = cublasCreate(&handle);
if (status != CUBLAS_STATUS_SUCCESS)
{
printf("CUBLAS initialization failed\n");
return EXIT_FAILURE;
}

status = cublasSetMatrix(n, n, sizeof(float), matrix, n, deviceMatrix, n);
if (status != CUBLAS_STATUS_SUCCESS)
{
printf("data download failed");
cudaFree(deviceMatrix);
cublasDestroy(handle);
return EXIT_FAILURE;
}

float alpha = 1;
float beta = 0;
cublasSgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N, n, n, n, &alpha, deviceMatrix, n, deviceMatrix, n, &beta, deviceMatrix, n);

status = cublasGetMatrix(n, n, sizeof(float), deviceMatrix, n, matrix, n);
if (status != CUBLAS_STATUS_SUCCESS)
{
printf("data upload failed");
cudaFree(deviceMatrix);
cublasDestroy(handle);
return EXIT_FAILURE;
}

cudaFree(deviceMatrix);
cublasDestroy(handle);
return EXIT_SUCCESS;
}

float* CpuMatrixMultiply(float* matrix, int size)
{
float* result = new float[size * size]();

// Copied from https://msdn.microsoft.com/en-us/library/hh873134.aspx
for (int row = 1; row <= size; row++)
{
for (int col = 1; col <= size; col++)
{
// Multiply the row of A by the column of B to get the row, column of product.
for (int inner = 1; inner <= size; inner++)
{
// result[row][col] += matrix[row][inner] * matrix[inner][col];
result[IDX2F(col, row, size)] += matrix[IDX2F(inner, row, size)] * matrix[IDX2F(col, inner, size)];
}
}
}

free(matrix);
return result;
}

int main(void)
{
// printf("Matrix * Matrix Test\n");
int size = 1000;
int runs = 10;

for (int run = 0; run != runs; run++)
{
printf("=== Test %d (Matrix * Matrix, Size = %d) ===\n\n", run + 1, size);
printf("RAM usage is: %f GB\n", size * size * sizeof(float) / 1000000000.0);

float* cpuMatrix = CreateMatrix(size);
cpuMatrix = CpuMatrixMultiply(cpuMatrix, size);

PrintMatrix(cpuMatrix, 5);

float* gpuMatrix = CreateMatrix(size);
CudaMatrixMultiply(gpuMatrix, size);
PrintMatrix(gpuMatrix, 5);

free(cpuMatrix);
free(gpuMatrix);
}
getchar();
return EXIT_SUCCESS;
}

Выход из ЦПУ версия MatrixMultiplication следующее, как и ожидалось:

4000 4000 4000 4000 4000
4000 4000 4000 4000 4000
4000 4000 4000 4000 4000
4000 4000 4000 4000 4000
4000 4000 4000 4000 4000

но результат вычисления GPU иногда является правильным (см. выше) или неправильным (?). Когда цикл выполняется в первый раз, результат всегда был правильным.

Я не могу найти ошибку в своем коде, и было бы здорово, если бы вы могли мне помочь.


Дополнительно, если я установлю size (в основном методе), например 16000 тогда мой драйвер падает, и я получаю сообщение об ошибке. Для этого я написал отчет об ошибке в NVidea, потому что мой компьютер зависал дважды. Но, может быть, это ошибка программирования?

Водитель: 364,72 (самый новый)
SDK: CUDA Toolkit 7.5
Видеокарта: NVidia GeForce GTX 960 (4 ГБ)
Windows 10 64Bit

Ошибка драйвера

Драйвер дисплея NVIDIA Драйвер режима ядра Windows версии 362.72 перестал отвечать и успешно восстановлен.

Редактировать: С помощью сообщества я обнаружил, что это проблема со сторожевым таймером. Смотрите ответ ниже.

1

Решение

Что касается второй части вопроса, то после замечания njuffa вы можете изменить настройки поведения драйвера, чтобы избежать ошибки при увеличении размера. Откройте NSIGHT Monitor и в Options, General, Microsoft Display Driver, измените на Ложь WDDM TDR включен поле.

иллюстрация настроек параметров NSIGHT Monitor

От спекуляция, 32-битные FPU-флопы должны быть около 2,4 TFLOPS с одинарной точностью, поэтому ваша операция с матрицей размером 16000 должна занять минимум 3,5 секунды. Отсюда и восстановление драйвера через 2 секунды.

1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector