From a5f68c946e47c2e40d46d7540a88c684673eb037 Mon Sep 17 00:00:00 2001
From: Hashim Sharif <hsharif3@tyler.cs.illinois.edu>
Date: Wed, 10 Jul 2019 02:38:58 -0500
Subject: [PATCH] TensorRT frontend changes for DepthwiseConv2D

---
 .../keras/frontend/approxhpvm_translator.py   | 41 +++++++++++++------
 llvm/projects/keras/frontend/utils.py         | 19 +++++++++
 2 files changed, 48 insertions(+), 12 deletions(-)
 create mode 100644 llvm/projects/keras/frontend/utils.py

diff --git a/llvm/projects/keras/frontend/approxhpvm_translator.py b/llvm/projects/keras/frontend/approxhpvm_translator.py
index b70b90cfac..f6f989ef85 100644
--- a/llvm/projects/keras/frontend/approxhpvm_translator.py
+++ b/llvm/projects/keras/frontend/approxhpvm_translator.py
@@ -4,6 +4,7 @@ import numpy as np
 from frontend.promise_translator import PromiseRtTranslator
 from frontend.hpvm_dfg_translator import HPVMTranslator
 from frontend.weight_utils import dumpLabels, dumpData, dumpConvWeights, dumpFcWeights, dumpFcBias
+from frontend.utils import *
 import keras
 import os
 
@@ -23,6 +24,7 @@ class DFG:
     layer_name = layer.__class__.__name__
     
     singleInLayers = {}
+    singleInLayers["DepthwiseConv2D"] = True
     singleInLayers["Conv2D"] = True
     singleInLayers["Dense"] = True   
     singleInLayers["MaxPooling2D"] = True   
@@ -145,7 +147,7 @@ class DFGNode:
       self.layer_name = layer.name  # unique layer identifier
       print (self.layer_name)
 
-      if layer_type == "Conv2D" or layer_type == "Dense":
+      if layer_type == "Conv2D" or layer_type == "DepthwiseConv2D" or  layer_type == "Dense":
         self.weights = layer.get_weights()[0]
         print("\t", self.weights.shape)
         self.use_bias = layer.use_bias
@@ -154,20 +156,23 @@ class DFGNode:
           self.use_bias = layer.use_bias
           self.bias_weights = layer.get_weights()[1]
           print("\t", self.bias_weights.shape)
-
-      if layer_type == "Conv2D":
+        
+          
+      if layer_type == "Conv2D" or layer_type == "DepthwiseConv2D":
         self.padding = layer.padding
         self.strides = layer.strides
         print("\t", self.strides)
         print("\tPadding = ", self.padding)
-      
+
+        
       if layer_type == "MaxPooling2D" or layer_type == "AveragePooling2D":
         self.pool_size = layer.pool_size
         self.strides = layer.strides
         print("\t pool_size = ", self.pool_size)
         print("\t strides = ", self.strides)
-               
-      if layer_type == "Conv2D" or layer_type == "Dense" or layer_type == "Activation":
+
+        
+      if nodeHasActivation(self):  
         self.activation_type = layer.activation.__name__
         print ("\t Activation = ", self.activation_type)
   
@@ -317,7 +322,7 @@ class TensorRtTranslator:
   
   def hasBiasAdd(self, cur_node):
 
-    if cur_node.layer_type == "Conv2D" or cur_node.layer_type == "Dense":
+    if nodeHasBias(cur_node):
       return cur_node.use_bias
 
     return False
@@ -325,8 +330,8 @@ class TensorRtTranslator:
 
   def hasActivation(self, cur_node):
 
-    if cur_node.layer_type == "Conv2D" or cur_node.layer_type == "Dense":
-      return  cur_node.activation_type != "linear" 
+    if nodeHasActivation(cur_node):
+      return cur_node.activation_type != "linear" 
 
     return False
 
@@ -355,7 +360,7 @@ class TensorRtTranslator:
     out_var_name1 = self.getVariableName(cur_node)    
     layer_type = cur_node.layer_type
         
-    if layer_type == "Conv2D":
+    if layer_type == "Conv2D" or layer_type == "DepthwiseConv2D":
       input_var_name = self.getSingleInputName(cur_node)
       weights = cur_node.weights
       strides = cur_node.strides
@@ -379,7 +384,14 @@ class TensorRtTranslator:
       inst_str += str(padding) + ", "
       inst_str += str(strides[0]) + ", "
       inst_str += str(strides[1]) + ", "
-      inst_str += "1, 0); \n"
+      inst_str += "1, "
+
+      if layer_type == "DepthwiseConv2D":
+        C = weights.shape[2]
+        inst_str += str(C) + "); \n"
+      else:
+        inst_str += "1); \n"
+        
 
       self.program_str += inst_str
 
@@ -501,7 +513,7 @@ class TensorRtTranslator:
       layer_type = layer.__class__.__name__
       layer_name = layer.name
 
-      if layer_type == "Conv2D":
+      if layer_type == "Conv2D" or layer_type == "DepthwiseConv2D":
         weights = layer.get_weights()[0]
         w_name = layer_name + "_w"
         
@@ -522,6 +534,11 @@ class TensorRtTranslator:
         file_path_str += unique_file_name + "\"); \n"
         self.weight_str += file_path_str
 
+        # NOTE: Special handling for DepthwiseConv2D
+        if layer_type == "DepthwiseConv2D":
+          N = C
+          C = 1   
+        
         # FIXME: Be flexible for datatypes (currently only FP32 weights)
         # NOTE: '0' specified for floating point type
         self.weight_str += "void* " + w_name + " = " + " readTrainedWeights("
diff --git a/llvm/projects/keras/frontend/utils.py b/llvm/projects/keras/frontend/utils.py
new file mode 100644
index 0000000000..6343dd9eec
--- /dev/null
+++ b/llvm/projects/keras/frontend/utils.py
@@ -0,0 +1,19 @@
+
+
+
+
+def nodeHasBias(cur_node):
+    
+  if cur_node.layer_type == "Conv2D" or cur_node.layer_type == "DepthwiseConv2D" or cur_node.layer_type == "Dense":
+    return True
+  else:
+    return False
+      
+
+def nodeHasActivation(cur_node):
+    
+  if cur_node.layer_type == "Conv2D" or cur_node.layer_type == "DepthwiseConv2D" \
+     or cur_node.layer_type == "Dense" or cur_node.layer_type == "Activation":
+    return True
+  else:
+    return False
-- 
GitLab