Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support cuDNN CTC functions #1769

Merged
merged 14 commits into from Apr 8, 2019
23 changes: 23 additions & 0 deletions cupy/cuda/cudnn.pxd
Expand Up @@ -115,6 +115,9 @@ cpdef enum:
CUDNN_BATCHNORM_SPATIAL = 1
CUDNN_BATCHNORM_SPATIAL_PERSISTENT = 2

CUDNN_CTC_LOSS_ALGO_DETERMINISTIC = 0
CUDNN_CTC_LOSS_ALGO_NON_DETERMINISTIC = 1

CUDNN_RNN_RELU = 0
CUDNN_RNN_TANH = 1
CUDNN_LSTM = 2
Expand Down Expand Up @@ -445,6 +448,26 @@ cpdef dropoutBackward(
size_t reserveSpace, size_t reserveSpaceSizeInBytes)


###############################################################################
# CTC
###############################################################################

cpdef size_t createCTCLossDescriptor() except? 0
cpdef destroyCTCLossDescriptor(size_t ctcLossDesc)
cpdef setCTCLossDescriptor(size_t ctcLossDesc, int dataType)
cpdef getCTCLossDescriptor(size_t ctcLossDesc)
cpdef getCTCLossWorkspaceSize(
size_t handle, size_t probsDesc, size_t gradientsDesc,
size_t labels, size_t labelLengths, size_t inputLengths,
int algo, size_t ctcLossDesc)
cpdef CTCLoss(
size_t handle, size_t probsDesc,
size_t probs, size_t labels, size_t labelLengths, size_t inputLengths,
size_t costs, size_t gradientsDesc, size_t gradients,
int algo, size_t ctcLossDesc,
size_t workspace, size_t workSpaceSizeInBytes)


###############################################################################
# RNN
###############################################################################
Expand Down
73 changes: 73 additions & 0 deletions cupy/cuda/cudnn.pyx
Expand Up @@ -73,6 +73,7 @@ cdef extern from "cupy_cudnn.h" nogil:
ctypedef int NanPropagation 'cudnnNanPropagation_t'
ctypedef int PoolingMode 'cudnnPoolingMode_t'
ctypedef int RNNInputMode 'cudnnRNNInputMode_t'
ctypedef int CTCLossAlgo 'cudnnCTCLossAlgo_t'
ctypedef int RNNMode 'cudnnRNNMode_t'
ctypedef int RNNAlgo 'cudnnRNNAlgo_t'
ctypedef int RNNDataLayout 'cudnnRNNDataLayout_t'
Expand All @@ -94,6 +95,7 @@ cdef extern from "cupy_cudnn.h" nogil:
ctypedef void* FilterDescriptor 'cudnnFilterDescriptor_t'
ctypedef void* Handle 'cudnnHandle_t'
ctypedef void* PoolingDescriptor 'cudnnPoolingDescriptor_t'
ctypedef void* CTCLossDescriptor 'cudnnCTCLossDescriptor_t'
ctypedef void* RNNDescriptor 'cudnnRNNDescriptor_t'
ctypedef void* RNNDataDescriptor 'cudnnRNNDataDescriptor_t'
ctypedef void* PersistentRNNPlan 'cudnnPersistentRNNPlan_t'
Expand Down Expand Up @@ -445,6 +447,24 @@ cdef extern from "cupy_cudnn.h" nogil:
TensorDescriptor dydesc, void* dy, TensorDescriptor dxdesc,
void* dx, void* reserveSpace, size_t reserveSpaceSizeInBytes)

# CTC
int cudnnCreateCTCLossDescriptor(CTCLossDescriptor* ctcLossDesc)
int cudnnDestroyCTCLossDescriptor(CTCLossDescriptor ctcLossDesc)
int cudnnSetCTCLossDescriptor(CTCLossDescriptor ctcLossDesc,
DataType dataType)
int cudnnGetCTCLossDescriptor(CTCLossDescriptor ctcLossDesc,
DataType* dataType)
int cudnnGetCTCLossWorkspaceSize(
Handle handle, TensorDescriptor probsDesc,
TensorDescriptor gradientsDesc, int* labels,
int* labelLengths, int* inputLengths, CTCLossAlgo algo,
CTCLossDescriptor ctcLossDesc, size_t* sizeInBytes)
int cudnnCTCLoss(
Handle handle, TensorDescriptor probsDesc,
void* probs, int* labels, int* labelLengths, int* inputLengths,
void* costs, TensorDescriptor gradientsDesc, void* gradients,
CTCLossAlgo algo, CTCLossDescriptor ctcLossDesc,
void* workspace, size_t workSpaceSizeInBytes)
# RNN
int cudnnCreateRNNDescriptor(RNNDescriptor* rnnDesc)
int cudnnDestroyRNNDescriptor(RNNDescriptor rnnDesc)
Expand Down Expand Up @@ -1684,6 +1704,59 @@ cpdef dropoutBackward(
check_status(status)


###############################################################################
# CTC
###############################################################################
cpdef size_t createCTCLossDescriptor() except? 0:
cdef CTCLossDescriptor desc
status = cudnnCreateCTCLossDescriptor(&desc)
check_status(status)
return <size_t>desc

cpdef destroyCTCLossDescriptor(size_t ctcLossDesc):
status = cudnnDestroyCTCLossDescriptor(<CTCLossDescriptor>ctcLossDesc)
check_status(status)

cpdef setCTCLossDescriptor(size_t ctcLossDesc, int dataType):
status = cudnnSetCTCLossDescriptor(
<CTCLossDescriptor>ctcLossDesc, <DataType>dataType)
check_status(status)

cpdef getCTCLossDescriptor(size_t ctcLossDesc):
cdef DataType compType
status = cudnnGetCTCLossDescriptor(<CTCLossDescriptor>ctcLossDesc,
&compType)
check_status(status)
return compType

cpdef getCTCLossWorkspaceSize(
aonotas marked this conversation as resolved.
Show resolved Hide resolved
size_t handle, size_t probsDesc, size_t gradientsDesc,
size_t labels, size_t labelLengths, size_t inputLengths,
int algo, size_t ctcLossDesc):
aonotas marked this conversation as resolved.
Show resolved Hide resolved
cdef size_t sizeInBytes
status = cudnnGetCTCLossWorkspaceSize(
<Handle>handle, <TensorDescriptor>probsDesc,
<TensorDescriptor>gradientsDesc,
<int*>labels, <int*>labelLengths, <int*>inputLengths,
<CTCLossAlgo>algo, <CTCLossDescriptor>ctcLossDesc, &sizeInBytes)
check_status(status)
return sizeInBytes

cpdef CTCLoss(
size_t handle, size_t probsDesc,
size_t probs, size_t labels, size_t labelLengths, size_t inputLengths,
size_t costs, size_t gradientsDesc, size_t gradients,
int algo, size_t ctcLossDesc,
size_t workspace, size_t workSpaceSizeInBytes):
status = cudnnCTCLoss(
<Handle>handle, <TensorDescriptor>probsDesc, <void*>probs,
<int*>labels, <int*>labelLengths, <int*>inputLengths,
<void*>costs, <TensorDescriptor>gradientsDesc, <void*>gradients,
<CTCLossAlgo>algo, <CTCLossDescriptor>ctcLossDesc,
<void*>workspace, <size_t>workSpaceSizeInBytes)
check_status(status)


###############################################################################
# RNN
###############################################################################
Expand Down
24 changes: 23 additions & 1 deletion cupy/cuda/cupy_cudnn.h
Expand Up @@ -660,6 +660,28 @@ cudnnStatus_t cudnnReduceTensor(...) {


typedef enum {} cudnnMathType_t;
typedef enum {} cudnnCTCLossAlgo_t;
typedef void* cudnnCTCLossDescriptor_t;

// CTC
cudnnStatus_t cudnnCreateCTCLossDescriptor(...) {
return CUDNN_STATUS_NOT_SUPPORTED;
}
cudnnStatus_t cudnnDestroyCTCLossDescriptor(...) {
return CUDNN_STATUS_NOT_SUPPORTED;
}
cudnnStatus_t cudnnSetCTCLossDescriptor(...) {
return CUDNN_STATUS_NOT_SUPPORTED;
}
cudnnStatus_t cudnnGetCTCLossDescriptor(...) {
return CUDNN_STATUS_NOT_SUPPORTED;
}
cudnnStatus_t cudnnGetCTCLossWorkspaceSize(...) {
return CUDNN_STATUS_NOT_SUPPORTED;
}
cudnnStatus_t cudnnCTCLoss(...) {
return CUDNN_STATUS_NOT_SUPPORTED;
}

cudnnStatus_t cudnnSetConvolutionMathType(...) {
return CUDNN_STATUS_NOT_SUPPORTED;
Expand Down Expand Up @@ -775,7 +797,7 @@ typedef void* cudnnRNNDataDescriptor_t;

typedef enum {} cudnnRNNDataLayout_t;
typedef enum {} cudnnRNNPaddingMode_t;

cudnnStatus_t cudnnSetRNNPaddingMode(...) {
return CUDNN_STATUS_NOT_SUPPORTED;
}
Expand Down
7 changes: 7 additions & 0 deletions cupy/cudnn.pyx
Expand Up @@ -382,6 +382,13 @@ def set_dropout_descriptor(desc, handle, dropout):
cudnn.setDropoutDescriptor(desc.value, handle, dropout, 0, 0, 0)


def create_ctc_loss_descriptor(data_type):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to hide descriptor and wrap cuDNN interface because raw cuDNN API is too complex.

This is high level API example.

def activation_forward(core.ndarray x, int mode, double coef=0.0):

Cloud you remove this function from this PR?

Copy link
Contributor Author

@aonotas aonotas Nov 2, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK. Thank you for your comment.
Do you mean should I define the other high level API function like following?

# in cupy/cudnn.pyx
def ctc_loss(data_type, other_args_for_cudnnCTCLoss):
    # create descriptor
    desc = Descriptor(cudnn.createCTCLossDescriptor(),
                    py_cudnn.destroyCTCLossDescriptor)
    cudnn.setCTCLossDescriptor(desc.value, data_type)

     # compute workspace
     getCTCLossWorkspaceSize(hoge, worksize)
     # allocate worksize
     workspace = ...
     # compute CTC loss
      CTCLoss(hoge, workspace, other_args_for_cudnnCTCLoss)
      return loss, gradients

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, something like that.

Copy link
Member

@okuta okuta Dec 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cloud you rename this function or delete this?

Suggested change
def create_ctc_loss_descriptor(data_type):
def _create_ctc_loss_descriptor(data_type):

desc = Descriptor(cudnn.createCTCLossDescriptor(),
py_cudnn.destroyCTCLossDescriptor)
cudnn.setCTCLossDescriptor(desc.value, data_type)
return desc


def create_rnn_descriptor(hidden_size, num_layers, dropout_desc,
input_mode, direction, mode, data_type, algo=None):
desc = Descriptor(cudnn.createRNNDescriptor(),
Expand Down