initial commit
This commit is contained in:
@@ -0,0 +1,3 @@
|
|||||||
|
*~
|
||||||
|
build/
|
||||||
|
.vscode/
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
|
||||||
|
project (tkDNN)
|
||||||
|
|
||||||
|
find_package(CUDA QUIET REQUIRED)
|
||||||
|
|
||||||
|
|
||||||
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include ${CUDA_INCLUDE_DIRS})
|
||||||
|
add_library(tkDNN SHARED src/Layer.cpp src/LayerWgs.cpp src/Dense.cpp src/Activation.cpp src/Network.cpp src/utils.cpp)
|
||||||
|
|
||||||
|
add_executable(tkDNNtest tests/test.cpp)
|
||||||
|
message(${CUDA_LIBRARIES})
|
||||||
|
target_link_libraries(tkDNNtest tkDNN ${CUDA_LIBRARIES} ${CUDA_CUBLAS_LIBRARIES} /usr/local/cuda-8.0/cudnn/libcudnn.so)
|
||||||
+104
@@ -0,0 +1,104 @@
|
|||||||
|
#ifndef LAYER_H
|
||||||
|
#define LAYER_H
|
||||||
|
|
||||||
|
#include<iostream>
|
||||||
|
#include "utils.h"
|
||||||
|
#include "Network.h"
|
||||||
|
|
||||||
|
namespace tkDNN {
|
||||||
|
|
||||||
|
/**
|
||||||
|
Data rapresentation beetween layers
|
||||||
|
*/
|
||||||
|
struct dataDim_t {
|
||||||
|
|
||||||
|
int n, c, h, w, l;
|
||||||
|
|
||||||
|
dataDim_t() : n(1), c(1), h(1), w(1), l(1) {};
|
||||||
|
|
||||||
|
dataDim_t(int _n, int _c, int _h, int _w, int _l = 1) :
|
||||||
|
n(_n), c(_c), h(_h), w(_w), l(_l) {};
|
||||||
|
|
||||||
|
void print() {
|
||||||
|
std::cout<<"Data dim: "<<n<<" "<<c<<" "<<h<<" "<<w<<" "<<l<<"\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
int tot() {
|
||||||
|
return n*c*h*w*l;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Simple layer Father class
|
||||||
|
*/
|
||||||
|
class Layer {
|
||||||
|
|
||||||
|
public:
|
||||||
|
Layer(Network *net, dataDim_t input_dim);
|
||||||
|
virtual ~Layer();
|
||||||
|
|
||||||
|
value_type* infer(dataDim_t &dim, value_type* srcData) {
|
||||||
|
std::cout<<"No infer action for this layer\n";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Network *net;
|
||||||
|
dataDim_t input_dim;
|
||||||
|
cudnnTensorDescriptor_t srcTensorDesc, dstTensorDesc;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Father class of all layer that need to load trained weights
|
||||||
|
*/
|
||||||
|
class LayerWgs : public Layer {
|
||||||
|
|
||||||
|
public:
|
||||||
|
LayerWgs(Network *net, dataDim_t input_dim,
|
||||||
|
int inputs, int outputs, int kh, int kw, int kt,
|
||||||
|
const char* fname_weights, const char* fname_bias);
|
||||||
|
virtual ~LayerWgs();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int inputs, outputs;
|
||||||
|
std::string weights_path, bias_path;
|
||||||
|
|
||||||
|
value_type *data_h, *data_d;
|
||||||
|
value_type *bias_h, *bias_d;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Dense (full interconnection) layer
|
||||||
|
*/
|
||||||
|
class Dense : public LayerWgs {
|
||||||
|
|
||||||
|
public:
|
||||||
|
Dense(Network *net, dataDim_t in_dim, int out_ch,
|
||||||
|
const char* fname_weights, const char* fname_bias);
|
||||||
|
virtual ~Dense();
|
||||||
|
|
||||||
|
value_type* infer(dataDim_t &dim, value_type* srcData);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
value_type *dstData; //where results will be putted
|
||||||
|
int out_ch;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Activation layer (it doesnt need weigths)
|
||||||
|
*/
|
||||||
|
class Activation : public Layer {
|
||||||
|
|
||||||
|
public:
|
||||||
|
Activation(Network *net, dataDim_t input_dim, cudnnActivationMode_t act_mode);
|
||||||
|
virtual ~Activation();
|
||||||
|
|
||||||
|
value_type* infer(dataDim_t &dim, value_type* srcData);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
cudnnActivationMode_t act_mode;
|
||||||
|
value_type *dstData; //where results will be putted
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //LAYER_H
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef NETWORK_H
|
||||||
|
#define NETWORK_H
|
||||||
|
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
namespace tkDNN {
|
||||||
|
|
||||||
|
class Network {
|
||||||
|
|
||||||
|
public:
|
||||||
|
Network();
|
||||||
|
virtual ~Network();
|
||||||
|
|
||||||
|
cudnnDataType_t dataType;
|
||||||
|
cudnnTensorFormat_t tensorFormat;
|
||||||
|
cudnnHandle_t cudnnHandle;
|
||||||
|
cublasHandle_t cublasHandle;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif //NETWORK_H
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
#ifndef UTILS_H
|
||||||
|
#define UTILS_H
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "cuda.h"
|
||||||
|
#include "cuda_runtime_api.h"
|
||||||
|
#include <cublas_v2.h>
|
||||||
|
#include <cudnn.h>
|
||||||
|
|
||||||
|
#define value_type float
|
||||||
|
|
||||||
|
|
||||||
|
#define TIMER_START timespec start, end; \
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &start);
|
||||||
|
|
||||||
|
#define TIMER_STOP clock_gettime(CLOCK_MONOTONIC, &end); \
|
||||||
|
double t_ns = ((double)(end.tv_sec - start.tv_sec) * 1.0e9 + \
|
||||||
|
(double)(end.tv_nsec - start.tv_nsec))/1.0e6; \
|
||||||
|
std::cout<<"Time:"<<std::setw(16)<<t_ns<<" ms\n";
|
||||||
|
|
||||||
|
|
||||||
|
/********************************************************
|
||||||
|
* Prints the error message, and exits
|
||||||
|
* ******************************************************/
|
||||||
|
#define EXIT_WAIVED 0
|
||||||
|
|
||||||
|
#define FatalError(s) { \
|
||||||
|
std::stringstream _where, _message; \
|
||||||
|
_where << __FILE__ << ':' << __LINE__; \
|
||||||
|
_message << std::string(s) + "\n" << __FILE__ << ':' << __LINE__;\
|
||||||
|
std::cerr << _message.str() << "\nAborting...\n"; \
|
||||||
|
cudaDeviceReset(); \
|
||||||
|
exit(EXIT_FAILURE); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define checkCUDNN(status) { \
|
||||||
|
std::stringstream _error; \
|
||||||
|
if (status != CUDNN_STATUS_SUCCESS) { \
|
||||||
|
_error << "CUDNN failure: " <<cudnnGetErrorString(status); \
|
||||||
|
FatalError(_error.str()); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define checkCuda(status) { \
|
||||||
|
std::stringstream _error; \
|
||||||
|
if (status != 0) { \
|
||||||
|
_error << "Cuda failure: "<<cudaGetErrorString(status); \
|
||||||
|
FatalError(_error.str()); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define checkERROR(status) { \
|
||||||
|
std::stringstream _error; \
|
||||||
|
if (status != 0) { \
|
||||||
|
_error << "Generic failure: " << status; \
|
||||||
|
FatalError(_error.str()); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
void readBinaryFile(const char* fname, int size, value_type** data_h, value_type** data_d);
|
||||||
|
void printDeviceVector(int size, value_type* vec_d);
|
||||||
|
void resize(int size, value_type **data);
|
||||||
|
|
||||||
|
#endif //UTILS_H
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "Layer.h"
|
||||||
|
|
||||||
|
namespace tkDNN {
|
||||||
|
|
||||||
|
Activation::Activation(Network *net, dataDim_t input_dim, cudnnActivationMode_t act_mode) :
|
||||||
|
Layer(net, input_dim) {
|
||||||
|
|
||||||
|
this->act_mode = act_mode;
|
||||||
|
checkCuda( cudaMalloc(&dstData, input_dim.tot()*sizeof(value_type)) );
|
||||||
|
|
||||||
|
checkCUDNN( cudnnSetTensor4dDescriptor(srcTensorDesc,
|
||||||
|
net->tensorFormat,
|
||||||
|
net->dataType,
|
||||||
|
input_dim.n, input_dim.c,
|
||||||
|
input_dim.h, input_dim.w) );
|
||||||
|
checkCUDNN( cudnnSetTensor4dDescriptor(dstTensorDesc,
|
||||||
|
net->tensorFormat,
|
||||||
|
net->dataType,
|
||||||
|
input_dim.n, input_dim.c,
|
||||||
|
input_dim.h, input_dim.w) );
|
||||||
|
}
|
||||||
|
|
||||||
|
Activation::~Activation() {
|
||||||
|
|
||||||
|
checkCuda( cudaFree(dstData) );
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type* Activation::infer(dataDim_t &dim, value_type* srcData) {
|
||||||
|
|
||||||
|
value_type alpha = value_type(1);
|
||||||
|
value_type beta = value_type(0);
|
||||||
|
checkCUDNN( cudnnActivationForward(net->cudnnHandle,
|
||||||
|
act_mode,
|
||||||
|
&alpha,
|
||||||
|
srcTensorDesc,
|
||||||
|
srcData,
|
||||||
|
&beta,
|
||||||
|
dstTensorDesc,
|
||||||
|
dstData) );
|
||||||
|
|
||||||
|
return dstData;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "Layer.h"
|
||||||
|
|
||||||
|
namespace tkDNN {
|
||||||
|
|
||||||
|
Dense::Dense(Network *net, dataDim_t in_dim,
|
||||||
|
int out_ch, const char* fname_weights, const char* fname_bias) :
|
||||||
|
LayerWgs(net, in_dim, in_dim.tot(), out_ch, 1, 1, 1, fname_weights, fname_bias) {
|
||||||
|
|
||||||
|
this->out_ch = out_ch;
|
||||||
|
//allocate data for infer result
|
||||||
|
checkCuda( cudaMalloc(&dstData, outputs*sizeof(value_type)) );
|
||||||
|
}
|
||||||
|
|
||||||
|
Dense::~Dense() {
|
||||||
|
|
||||||
|
checkCuda( cudaFree(dstData) );
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type* Dense::infer(dataDim_t &dim, value_type* srcData) {
|
||||||
|
|
||||||
|
if (dim.n != 1)
|
||||||
|
FatalError("Not Implemented");
|
||||||
|
|
||||||
|
int dim_x = dim.tot();
|
||||||
|
int dim_y = outputs;
|
||||||
|
|
||||||
|
if (dim_x != inputs)
|
||||||
|
FatalError("Input mismatch");
|
||||||
|
|
||||||
|
value_type alpha = value_type(1), beta = value_type(1);
|
||||||
|
// place bias into dstData
|
||||||
|
checkCuda( cudaMemcpy(dstData, bias_d, dim_y*sizeof(value_type), cudaMemcpyDeviceToDevice) );
|
||||||
|
|
||||||
|
//do matrix moltiplication
|
||||||
|
checkERROR( cublasSgemv(net->cublasHandle, CUBLAS_OP_T,
|
||||||
|
dim_x, dim_y,
|
||||||
|
&alpha,
|
||||||
|
data_d, dim_x,
|
||||||
|
srcData, 1,
|
||||||
|
&beta,
|
||||||
|
dstData, 1) );
|
||||||
|
|
||||||
|
//update data dimensions
|
||||||
|
dim.h = 1;
|
||||||
|
dim.w = 1;
|
||||||
|
dim.l = 1;
|
||||||
|
dim.c = dim_y;
|
||||||
|
|
||||||
|
return dstData;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "Layer.h"
|
||||||
|
|
||||||
|
namespace tkDNN {
|
||||||
|
|
||||||
|
Layer::Layer(Network *net, dataDim_t in_dim) {
|
||||||
|
|
||||||
|
this->net = net;
|
||||||
|
this->input_dim = in_dim;
|
||||||
|
|
||||||
|
checkCUDNN( cudnnCreateTensorDescriptor(&srcTensorDesc) );
|
||||||
|
checkCUDNN( cudnnCreateTensorDescriptor(&dstTensorDesc) );
|
||||||
|
}
|
||||||
|
|
||||||
|
Layer::~Layer() {
|
||||||
|
|
||||||
|
checkCUDNN( cudnnDestroyTensorDescriptor(srcTensorDesc) );
|
||||||
|
checkCUDNN( cudnnDestroyTensorDescriptor(dstTensorDesc) );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "Layer.h"
|
||||||
|
|
||||||
|
namespace tkDNN {
|
||||||
|
|
||||||
|
LayerWgs::LayerWgs(Network *net, dataDim_t in_dim,
|
||||||
|
int inputs, int outputs, int kh, int kw, int kl,
|
||||||
|
const char* fname_weights, const char* fname_bias) : Layer(net, in_dim) {
|
||||||
|
|
||||||
|
this->inputs = inputs;
|
||||||
|
this->outputs = outputs;
|
||||||
|
this->weights_path = std::string(fname_weights);
|
||||||
|
this->bias_path = std::string(fname_bias);
|
||||||
|
|
||||||
|
std::cout<<"Reading weights: I="<<inputs<<" O="<<outputs<<" KERNEL="<<kh<<"x"<<kw<<"x"<<kl<<"\n";
|
||||||
|
readBinaryFile(weights_path.c_str(), inputs*outputs*kh*kw*kl, &data_h, &data_d);
|
||||||
|
readBinaryFile(bias_path.c_str(), outputs, &bias_h, &bias_d);
|
||||||
|
}
|
||||||
|
|
||||||
|
LayerWgs::~LayerWgs() {
|
||||||
|
|
||||||
|
delete [] data_h;
|
||||||
|
delete [] bias_h;
|
||||||
|
checkCuda( cudaFree(data_d) );
|
||||||
|
checkCuda( cudaFree(bias_d) );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "Network.h"
|
||||||
|
|
||||||
|
namespace tkDNN {
|
||||||
|
|
||||||
|
Network::Network() {
|
||||||
|
|
||||||
|
std::cout<<"New NETWORK with CUDNN v"<<float(cudnnGetVersion())/1000<<"\n";
|
||||||
|
dataType = CUDNN_DATA_FLOAT;
|
||||||
|
tensorFormat = CUDNN_TENSOR_NCHW;
|
||||||
|
|
||||||
|
checkCUDNN( cudnnCreate(&cudnnHandle) );
|
||||||
|
checkERROR( cublasCreate(&cublasHandle) );
|
||||||
|
}
|
||||||
|
|
||||||
|
Network::~Network() {
|
||||||
|
|
||||||
|
checkCUDNN( cudnnDestroy(cudnnHandle) );
|
||||||
|
checkERROR( cublasDestroy(cublasHandle) );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
void readBinaryFile(const char* fname, int size, value_type** data_h, value_type** data_d)
|
||||||
|
{
|
||||||
|
std::ifstream dataFile (fname, std::ios::in | std::ios::binary);
|
||||||
|
std::stringstream error_s;
|
||||||
|
if (!dataFile)
|
||||||
|
{
|
||||||
|
error_s << "Error opening file " << fname;
|
||||||
|
FatalError(error_s.str());
|
||||||
|
}
|
||||||
|
int size_b = size*sizeof(value_type);
|
||||||
|
*data_h = new value_type[size];
|
||||||
|
if (!dataFile.read ((char*) *data_h, size_b))
|
||||||
|
{
|
||||||
|
error_s << "Error reading file " << fname;
|
||||||
|
FatalError(error_s.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
checkCuda( cudaMalloc(data_d, size_b) );
|
||||||
|
checkCuda( cudaMemcpy(*data_d, *data_h,
|
||||||
|
size_b,
|
||||||
|
cudaMemcpyHostToDevice) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void printDeviceVector(int size, value_type* vec_d)
|
||||||
|
{
|
||||||
|
value_type *vec;
|
||||||
|
vec = new value_type[size];
|
||||||
|
cudaDeviceSynchronize();
|
||||||
|
cudaMemcpy(vec, vec_d, size*sizeof(value_type), cudaMemcpyDeviceToHost);
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
std::cout << vec[i] << " ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
delete [] vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(int size, value_type **data)
|
||||||
|
{
|
||||||
|
if (*data != NULL)
|
||||||
|
checkCuda( cudaFree(*data) );
|
||||||
|
checkCuda( cudaMalloc(data, size*sizeof(value_type)) );
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#include<iostream>
|
||||||
|
#include "Layer.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
|
||||||
|
tkDNN::dataDim_t dim(1, 1, 10, 10);
|
||||||
|
dim.print();
|
||||||
|
tkDNN::Network net;
|
||||||
|
tkDNN::Dense d(&net, dim, 2, "ci", "lol");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user