Skip to content
This repository was archived by the owner on Aug 5, 2022. It is now read-only.

Commit 8012927

Browse files
author
jgong5
committed
Merge remote-tracking branch 'internal/release_1.0.2a'
2 parents 3bbc9f1 + 0da457c commit 8012927

26 files changed

+3790
-402
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ include(cmake/ConfigGen.cmake)
2929
caffe_option(CPU_ONLY "Build Caffe without CUDA support" OFF) # TODO: rename to USE_CUDA
3030
caffe_option(USE_OPENMP "Build Caffe with OpenMP support" ON )
3131
caffe_option(USE_CUDNN "Build Caffe with cuDNN library support" ON IF NOT CPU_ONLY)
32-
caffe_option(USE_MKL2017_AS_DEFAULT_ENGINE "Use MKL2017 primitives for supported layers" OFF)
32+
caffe_option(USE_MKL2017_AS_DEFAULT_ENGINE "Use MKL2017 primitives for supported layers" ON)
3333
caffe_option(USE_MKLDNN_AS_DEFAULT_ENGINE "Use MKL-DNN primitives for supported layers" OFF)
3434
caffe_option(BUILD_SHARED_LIBS "Build shared libraries" ON)
3535
caffe_option(BUILD_python "Build Python wrapper" ON)

Makefile.config.example

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@
4343
# CPU-only switch (uncomment to build without GPU support).
4444
CPU_ONLY := 1
4545

46-
# USE_MKL2017_AS_DEFAULT_ENGINE flag is OBSOLETE
47-
# Put this at the top your train_val.protoxt or solver.prototxt file:
46+
USE_MKL2017_AS_DEFAULT_ENGINE := 1
47+
# or put this at the top your train_val.protoxt or solver.prototxt file:
4848
# engine: "MKL2017"
4949
# or use this option with caffe tool:
5050
# -engine "MKL2017"

docs/release_notes.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,6 @@ This Caffe version is seflcontained. This means that newest version of Intel MKL
126126
* Set layer engine to `MKL2017` in prototxt file (model). Only this specific layer will be accelerated with new primitives.
127127
* Use -engine = MKL2017 in command line as an option during execution of caffe (training, scoring, benchmark)
128128

129-
Comment: there is obsolete method to compale with `USE_MKL2017_AS_DEFAULT_ENGINE := 1` in `Makefile.config`. This is obsolete solution - not recommended to use anymore.
130-
131129
### Building for GPU
132130
Caffe requires the CUDA `nvcc` compiler to compile its GPU code and CUDA driver for GPU operation.
133131
To install CUDA, go to the [NVIDIA CUDA website](https://developer.nvidia.com/cuda-downloads) and follow installation instructions there. Install the library and the latest standalone driver separately; the driver bundled with the library is usually out-of-date. **Warning!** The 331.* CUDA driver series has a critical performance issue: do not use it.

examples/pycaffe/tune_engine.py

Lines changed: 8 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,120 +1,9 @@
11
import os
22
import sys
3-
import copy
43
import argparse
5-
64
from caffe.proto import caffe_pb2
75
import google.protobuf.text_format as txtf
8-
9-
def readFile(filePath):
10-
lines = []
11-
file = open(filePath, 'r')
12-
for line in file.readlines():
13-
lines.append(line)
14-
file.close()
15-
16-
return lines
17-
18-
def writeFile(filePath, lines):
19-
file = open(filePath, 'w+')
20-
file.write(lines)
21-
file.close()
22-
23-
def parseLog(log):
24-
lines = readFile(log)
25-
model_start = False
26-
time_start = False
27-
model_lines = []
28-
time_lines = []
29-
for line in lines:
30-
trim_line = line.strip()
31-
if trim_line.endswith("Initializing net from parameters:"):
32-
model_start = True
33-
continue
34-
if model_start:
35-
if trim_line.find("Creating layer") <> -1:
36-
model_start = False
37-
continue
38-
model_lines.append(line)
39-
40-
if trim_line.endswith("Average time per layer:"):
41-
time_start = True
42-
continue
43-
if time_start:
44-
if trim_line.find("Average Forward pass") <> -1:
45-
time_start = False
46-
break
47-
time_lines.append(line)
48-
49-
model_lines = model_lines[1:]
50-
model_str = ""
51-
for line in model_lines:
52-
model_str = model_str + line
53-
54-
return (model_str, time_lines)
55-
56-
def parseTimeLines(timeLines):
57-
layer_map = {}
58-
for line in timeLines:
59-
trim_line = line.strip()
60-
items = trim_line.split("\t")
61-
layer_items = items[0].split(" ")
62-
layer_name = layer_items[-1]
63-
time_items = items[1].split(" ")
64-
if layer_name not in layer_map.keys():
65-
layer_map[layer_name] = (float)(time_items[1])
66-
else:
67-
layer_map[layer_name] = layer_map[layer_name] + (float)(time_items[1])
68-
69-
return layer_map
70-
71-
def parseModelStr(modelStr):
72-
net = caffe_pb2.NetParameter()
73-
txtf.Merge(modelStr, net)
74-
layer_model_map = {}
75-
global_engine = "CAFFE"
76-
if net.engine != "":
77-
global_engine = net.engine
78-
for index in range(0, len(net.layer)):
79-
engine = global_engine
80-
l = net.layer[index]
81-
if l.engine != "":
82-
engine = l.engine
83-
param_engine = -1
84-
if l.type == "Convolution" or l.type == "Deconvolution":
85-
if l.convolution_param.engine != "":
86-
param_engine = l.convolution_param.engine
87-
elif l.type == "BatchNorm":
88-
if l.batch_norm_param.engine != "":
89-
param_engine = l.batch_norm_param.engine
90-
elif l.type == "Concat":
91-
if l.concat_param.engine != "":
92-
param_engine = l.concat_param.engine
93-
elif l.type == "Eltwise":
94-
if l.eltwise_param.engine != "":
95-
param_engine = l.eltwise_param.engine
96-
elif l.type == "InnerProduct":
97-
if l.inner_product_param.engine != "":
98-
param_engine = l.inner_product_param.engine
99-
elif l.type == "LRN":
100-
if l.lrn_param.engine != "":
101-
param_engine = l.lrn_param.engine
102-
elif l.type == "Pooling":
103-
if l.pooling_param.engine != "":
104-
param_engine = l.pooling_param.engine
105-
elif l.type == "ReLU":
106-
if l.relu_param.engine != "":
107-
param_engine = l.relu_param.engine
108-
109-
if param_engine == 0 or param_engine == 1:
110-
engine = "CAFFE"
111-
elif param_engine == 3:
112-
engine = "MKL2017"
113-
elif param_engine == 4:
114-
engine = "MKLDNN"
115-
layer_model_map[l.name] = (index, engine, l)
116-
117-
return (net, layer_model_map)
6+
import utils
1187

1198
def selectOptimalEngine(layers):
1209
optimal_layer = None
@@ -140,9 +29,9 @@ def tuneEngine(logs, model):
14029
net = None
14130
for log in logs:
14231
log_name = os.path.basename(log)
143-
(model_str, time_lines) = parseLog(log)
144-
(net, layer_model_map) = parseModelStr(model_str)
145-
layer_time_map = parseTimeLines(time_lines)
32+
(model_str, time_lines) = utils.parseLog(log)
33+
(net, layer_model_map) = utils.parseModelStr(model_str)
34+
layer_time_map = utils.parseTimeLines(time_lines)
14635
for k, v in layer_model_map.items():
14736
if k not in layer_map.keys():
14837
layer_map[k] = [(v[0], v[1], layer_time_map[k], v[2])]
@@ -187,4 +76,8 @@ def genModel(net, model, optimal_layer_map):
18776
parser.add_argument('-v', '--version', action='version', version='%(prog)s 1.0')
18877

18978
params = parser.parse_args()
79+
if params.output == "":
80+
print "Please specify the output for tuned model with -o"
81+
sys.exit(1)
82+
19083
tuneEngine(params.logs, params.output)

examples/pycaffe/tune_model.py

Lines changed: 72 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,92 +1,88 @@
11
import os
2-
import datetime
3-
import copy
2+
import sys
43
import argparse
5-
64
from caffe.proto import caffe_pb2
75
import google.protobuf.text_format as txtf
8-
import caffe
9-
10-
def isWinogradApplicable(ic, oc, stride, kernel_size):
11-
if ic % 16 != 0:
12-
return False
13-
if oc % 16 != 0:
14-
return False
15-
if stride != 1:
16-
return False
17-
if kernel_size != 3:
18-
return False
19-
20-
return True
21-
22-
def genHybridModel(net, winogradLayers, modelName):
23-
newNet = copy.deepcopy(net)
24-
newNetName = modelName.split(".")[0] + "_hybrid.prototxt"
25-
for layer in winogradLayers:
26-
newNet.layer[layer].convolution_param.conv_algorithm = "winograd"
27-
with open(newNetName, 'w') as f:
28-
f.write(str(newNet))
29-
print "[INFO] Complete model tuning with Winograd:", newNetName
30-
31-
def tuneModelDefinition(model):
32-
net = caffe_pb2.NetParameter()
33-
with open(model) as f:
34-
s = f.read()
35-
txtf.Merge(s, net)
6+
import copy
7+
import utils
368

37-
net.name = 'Tuned model of ' + net.name
38-
output_layer_map = {}
9+
def genOptimalModel(net, mkldnn_direct_time_map, mkldnn_winograd_time_map, optimal_model):
3910
for index in range(0, len(net.layer)):
4011
l = net.layer[index]
41-
if l.type == ("Convolution"):
42-
stride = 0
43-
kernel_size = 0
44-
if len(l.convolution_param.stride) == 0:
45-
stride = 1
12+
if l.type == "Convolution":
13+
if mkldnn_winograd_time_map[l.name] < mkldnn_direct_time_map[l.name]:
14+
l.convolution_param.conv_algorithm = "winograd"
4615
else:
47-
stride = l.convolution_param.stride[0]
48-
kernel_size = l.convolution_param.kernel_size[0]
49-
ic = 0
50-
if l.bottom[0] in output_layer_map.keys():
51-
ic = output_layer_map[l.bottom[0]][4]
52-
oc = l.convolution_param.num_output
53-
output_layer_map[l.name] = (index, stride, kernel_size, ic, oc, True)
54-
elif l.type == ("InnerProduct"):
55-
oc = l.inner_product_param.num_output
56-
ic = 0
57-
if l.bottom[0] in output_layer_map.keys():
58-
ic = output_layer_map[l.bottom[0]][4]
59-
output_layer_map[l.name] = (index, 0, 0, ic, oc, False)
60-
elif l.type.endswith("Data") or l.type.endswith("Input"):
61-
# TODO: correct the output
62-
# dynamic_net = caffe.Net(model, caffe.TEST)
63-
# for k, v in dynamic_net.blobs.items():
64-
# dynamic_net_map[k] = v.data.shape
65-
ic = oc = 3
66-
output_layer_map[l.name] = (index, 0, 0, ic, oc, False)
67-
else:
68-
ic = 0
69-
if l.bottom[0] in output_layer_map.keys():
70-
ic = output_layer_map[l.bottom[0]][4]
71-
oc = ic
72-
output_layer_map[l.name] = (index, 0, 0, ic, oc, False)
73-
74-
winograd_convolutions = []
75-
for k,v in output_layer_map.items():
76-
if v[5] and isWinogradApplicable(v[3], v[4], v[1], v[2]):
77-
winograd_convolutions.append(v[0])
78-
79-
if len(winograd_convolutions) > 0:
80-
genHybridModel(net, winograd_convolutions, model)
81-
else:
82-
print "[INFO] No need to tune model with Winograd:", model
83-
16+
l.convolution_param.conv_algorithm = "direct"
17+
18+
with open(optimal_model, "w") as f:
19+
f.write(txtf.MessageToString(net, float_format=".17g"))
20+
21+
def tuneModelDefinition(model_path, iteration):
22+
working_dir = sys.path[0]
23+
caffe_path = os.path.join(working_dir, "..", "..", "build", "tools", "caffe")
24+
if not os.path.exists(caffe_path):
25+
print "Caffe binary does not exist; please build Caffe binary first."
26+
sys,exit(1)
27+
28+
base_model_name = os.path.basename(model_path)
29+
model_dir = os.path.dirname(model_path)
30+
winograd_model_name = base_model_name.split(".")[0] + "_winograd.prototxt"
31+
winograd_model_path = os.path.join(model_dir, winograd_model_name)
32+
direct_model_name = base_model_name.split(".")[0] + "_direct.prototxt"
33+
direct_model_path = os.path.join(model_dir, direct_model_name)
34+
35+
base_net = caffe_pb2.NetParameter()
36+
with open(model_path) as f:
37+
s = f.read()
38+
txtf.Merge(s, base_net)
39+
40+
direct_net = copy.deepcopy(base_net)
41+
for index in range(0, len(direct_net.layer)):
42+
l = direct_net.layer[index]
43+
if l.type == "Convolution":
44+
l.convolution_param.conv_algorithm = "direct"
45+
46+
with open(direct_model_path, "w") as f:
47+
f.write(txtf.MessageToString(direct_net, float_format=".17g"))
48+
49+
winograd_net = copy.deepcopy(base_net)
50+
for index in range(0, len(winograd_net.layer)):
51+
l = winograd_net.layer[index]
52+
if l.type == "Convolution":
53+
l.convolution_param.conv_algorithm = "winograd"
54+
55+
with open(winograd_model_path, "w") as f:
56+
f.write(txtf.MessageToString(winograd_net, float_format=".17g"))
57+
58+
mkldnn_direct_log = "mkldnn_direct.log"
59+
mkldnn_winograd_log = "mkldnn_winograd.log"
60+
mkldnn_direct_log_path = os.path.join(model_dir, mkldnn_direct_log)
61+
mkldnn_winograd_log_path = os.path.join(model_dir, mkldnn_winograd_log)
62+
63+
mkldnn_direct_command = caffe_path + " time -model " + direct_model_path + " -engine MKLDNN -iterations " + str(iteration) + " >& " + mkldnn_direct_log_path
64+
os.system(mkldnn_direct_command)
65+
mkldnn_winograd_command = caffe_path + " time -model " + winograd_model_path + " -engine MKLDNN -iterations " + str(iteration) + " >& " + mkldnn_winograd_log_path
66+
os.system(mkldnn_winograd_command)
67+
68+
(model_str, mkldnn_direct_time_lines) = utils.parseLog(mkldnn_direct_log_path)
69+
mkldnn_direct_layer_time_map = utils.parseTimeLines(mkldnn_direct_time_lines)
70+
(model_str, mkldnn_winograd_time_lines) = utils.parseLog(mkldnn_winograd_log_path)
71+
mkldnn_winograd_layer_time_map = utils.parseTimeLines(mkldnn_winograd_time_lines)
72+
73+
hybrid_model_name = base_model_name.split(".")[0] + "_hybrid.prototxt"
74+
hybrid_model_path = os.path.join(model_dir, hybrid_model_name)
75+
genOptimalModel(base_net, mkldnn_direct_layer_time_map, mkldnn_winograd_layer_time_map, hybrid_model_path)
76+
8477
if __name__ == '__main__':
8578
parser = argparse.ArgumentParser()
8679

8780
parser.add_argument('-m', '--model', action='store', dest='model', default="",
8881
help='require the model definition (prototxt)')
8982

83+
parser.add_argument('-i', '--iteration', action='store', dest='iterations', type=int, default=10,
84+
help='require iterations number to run the model')
85+
9086
parser.add_argument('-v', '--version', action='version', version='%(prog)s 1.0')
9187

9288
params = parser.parse_args()
@@ -96,4 +92,4 @@ def tuneModelDefinition(model):
9692
print "[ERROR] Please specify the model definition file with -m"
9793
exit(1)
9894

99-
tuneModelDefinition(model)
95+
tuneModelDefinition(params.model, params.iterations)

0 commit comments

Comments
 (0)