В настоящее время я делаю кое-что на Cuda C ++ для глубокого обучения (техника Карандаш и бумага), но застрял на странном поведении Cuda.
Вот мой класс:
class Matrix
{
public:
float* data;
int width;
int height;
Matrix();
Matrix(const Matrix&);
~Matrix();
void reset();
friend std::ostream& operator<<(std::ostream&, const Matrix*);
};
Его определение:
Matrix::Matrix()
{
}
Matrix::Matrix(const Matrix& copy) : width(copy.width), height(copy.height)
{
data = new float[width * height];
std::copy(copy.data, copy.data + width * height, data);
}
Matrix::~Matrix()
{
delete data;
}
void Matrix::reset()
{
memset(data, 0, width * height * sizeof(float));
}
std::ostream& operator<<(std::ostream& out, const Matrix* matrix)
{
for (int i = 1; i <= matrix->height * matrix->width; ++i)
out << matrix->data[i - 1] << (i % matrix->width == 0 ? "\n" : "\t");
return out;
}
А вот минимальный, полный и проверяемый пример:
__global__ void add_and_display(Matrix* dev_weights)
{
dev_weights->data[blockIdx.x * dev_weights->width + threadIdx.x] += 1.f;
}
int main()
{
Matrix* weights = new Matrix(), *dev_weights;
float* weights_elements;
//For the purpose of testing, creating a checked pattern Matrix
weights->width = 9;
weights->height = 9;
weights->data = new float[weights->width * weights->height];
for (int i = 0; i < weights->width * weights->height; ++i)
{
if (i % 2 == 0)
weights->data[i] = 0;
else
weights->data[i] = 1;
}
int weights_size = weights->width * weights->height * sizeof(float);
HANDLE_ERROR(cudaMalloc((void **)&weights_elements, weights_size));
//Allocate objects on the device
HANDLE_ERROR(cudaMalloc((void **)&dev_weights, sizeof(Matrix)));
//Copy the data to the object allocated on the device
HANDLE_ERROR(cudaMemcpy(dev_weights, weights, sizeof(Matrix), cudaMemcpyHostToDevice));
HANDLE_ERROR(cudaMemcpy(weights_elements, weights->data, weights_size, cudaMemcpyHostToDevice));
HANDLE_ERROR(cudaMemcpy(&(dev_weights->data), &weights_elements, sizeof(float*), cudaMemcpyHostToDevice));
add_and_display <<< weights->width, weights->height >>> (dev_weights);
HANDLE_ERROR(cudaDeviceSynchronize());
//Copy back data from device
float* hostPointer = new float[weights->width * weights->height];
HANDLE_ERROR(cudaMemcpy(weights, dev_weights, sizeof(Matrix), cudaMemcpyDeviceToHost));
HANDLE_ERROR(cudaMemcpy(hostPointer, weights->data, weights_size, cudaMemcpyDeviceToHost));
//Display and get errors here
cout << weights << endl;
cudaFree(dev_weights);
return 0;
}
Вот мой макрос для проверки ошибок:
static void HandleError(cudaError_t err, const char *file, int line) {
if (err != cudaSuccess) {
printf("%s in %s at line %d\n", cudaGetErrorString(err), file, line);
exit(EXIT_FAILURE);
}
}
#define HANDLE_ERROR( err ) (HandleError( err, __FILE__, __LINE__ ))
Так что проблема в том, что программа вылетает при попытке отобразить данные на хосте. Я думаю, копия с устройства не работает, но я не могу найти способ исправить это.
Спасибо, если вы можете помочь мне найти проблему.
РЕДАКТИРОВАТЬ 1: Упростил мой пост, чтобы его можно было проверить всем.