Skip to content
This repository was archived by the owner on Sep 27, 2019. It is now read-only.

Commit d583b5f

Browse files
saatvikspervazea
authored andcommitted
Workload Prediction (#1248)
* Integrating Eigen * Workload Prediction starter * Workload Prediction integrated - Pending testing * Fix for memory leaks * Sine wave test addition * Formatting changes + header updates * Installing Eigen as package instead of keeping third party * Addressed Code Review * On the fly model generation and cleanup * More memory leak fixes * Fixes according to review comments * Fixing permission on packages.sh and namespace fix
1 parent 78b85dc commit d583b5f

30 files changed

+989
-290
lines changed

cmake/Dependencies.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ find_library(TFlowC
4242
PATHS "/usr/local/lib")
4343
list(APPEND Peloton_LINKER_LIBS ${TFlowC})
4444

45+
# --[ Eigen3
46+
find_package(Eigen3 REQUIRED)
47+
include_directories(SYSTEM ${EIGEN3_INCLUDE_DIR})
48+
4549
# ---[ Libevent
4650
find_package(Libevent REQUIRED)
4751
include_directories(SYSTEM ${LIBEVENT_INCLUDE_DIRS})

cmake/Modules/FindEigen3.cmake

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# - Try to find Eigen3 lib
2+
#
3+
# This module supports requiring a minimum version, e.g. you can do
4+
# find_package(Eigen3 3.1.2)
5+
# to require version 3.1.2 or newer of Eigen3.
6+
#
7+
# Once done this will define
8+
#
9+
# EIGEN3_FOUND - system has eigen lib with correct version
10+
# EIGEN3_INCLUDE_DIR - the eigen include directory
11+
# EIGEN3_VERSION - eigen version
12+
#
13+
# This module reads hints about search locations from
14+
# the following enviroment variables:
15+
#
16+
# EIGEN3_ROOT
17+
# EIGEN3_ROOT_DIR
18+
19+
# Copyright (c) 2006, 2007 Montel Laurent, <[email protected]>
20+
# Copyright (c) 2008, 2009 Gael Guennebaud, <[email protected]>
21+
# Copyright (c) 2009 Benoit Jacob <[email protected]>
22+
# Redistribution and use is allowed according to the terms of the 2-clause BSD license.
23+
24+
if(NOT Eigen3_FIND_VERSION)
25+
if(NOT Eigen3_FIND_VERSION_MAJOR)
26+
set(Eigen3_FIND_VERSION_MAJOR 2)
27+
endif(NOT Eigen3_FIND_VERSION_MAJOR)
28+
if(NOT Eigen3_FIND_VERSION_MINOR)
29+
set(Eigen3_FIND_VERSION_MINOR 91)
30+
endif(NOT Eigen3_FIND_VERSION_MINOR)
31+
if(NOT Eigen3_FIND_VERSION_PATCH)
32+
set(Eigen3_FIND_VERSION_PATCH 0)
33+
endif(NOT Eigen3_FIND_VERSION_PATCH)
34+
35+
set(Eigen3_FIND_VERSION "${Eigen3_FIND_VERSION_MAJOR}.${Eigen3_FIND_VERSION_MINOR}.${Eigen3_FIND_VERSION_PATCH}")
36+
endif(NOT Eigen3_FIND_VERSION)
37+
38+
macro(_eigen3_check_version)
39+
file(READ "${EIGEN3_INCLUDE_DIR}/Eigen/src/Core/util/Macros.h" _eigen3_version_header)
40+
41+
string(REGEX MATCH "define[ \t]+EIGEN_WORLD_VERSION[ \t]+([0-9]+)" _eigen3_world_version_match "${_eigen3_version_header}")
42+
set(EIGEN3_WORLD_VERSION "${CMAKE_MATCH_1}")
43+
string(REGEX MATCH "define[ \t]+EIGEN_MAJOR_VERSION[ \t]+([0-9]+)" _eigen3_major_version_match "${_eigen3_version_header}")
44+
set(EIGEN3_MAJOR_VERSION "${CMAKE_MATCH_1}")
45+
string(REGEX MATCH "define[ \t]+EIGEN_MINOR_VERSION[ \t]+([0-9]+)" _eigen3_minor_version_match "${_eigen3_version_header}")
46+
set(EIGEN3_MINOR_VERSION "${CMAKE_MATCH_1}")
47+
48+
set(EIGEN3_VERSION ${EIGEN3_WORLD_VERSION}.${EIGEN3_MAJOR_VERSION}.${EIGEN3_MINOR_VERSION})
49+
if(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
50+
set(EIGEN3_VERSION_OK FALSE)
51+
else(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
52+
set(EIGEN3_VERSION_OK TRUE)
53+
endif(${EIGEN3_VERSION} VERSION_LESS ${Eigen3_FIND_VERSION})
54+
55+
if(NOT EIGEN3_VERSION_OK)
56+
57+
message(STATUS "Eigen3 version ${EIGEN3_VERSION} found in ${EIGEN3_INCLUDE_DIR}, "
58+
"but at least version ${Eigen3_FIND_VERSION} is required")
59+
endif(NOT EIGEN3_VERSION_OK)
60+
endmacro(_eigen3_check_version)
61+
62+
if (EIGEN3_INCLUDE_DIR)
63+
64+
# in cache already
65+
_eigen3_check_version()
66+
set(EIGEN3_FOUND ${EIGEN3_VERSION_OK})
67+
68+
else (EIGEN3_INCLUDE_DIR)
69+
70+
# search first if an Eigen3Config.cmake is available in the system,
71+
# if successful this would set EIGEN3_INCLUDE_DIR and the rest of
72+
# the script will work as usual
73+
find_package(Eigen3 ${Eigen3_FIND_VERSION} NO_MODULE QUIET)
74+
75+
if(NOT EIGEN3_INCLUDE_DIR)
76+
find_path(EIGEN3_INCLUDE_DIR NAMES signature_of_eigen3_matrix_library
77+
HINTS
78+
ENV EIGEN3_ROOT
79+
ENV EIGEN3_ROOT_DIR
80+
PATHS
81+
${CMAKE_INSTALL_PREFIX}/include
82+
${KDE4_INCLUDE_DIR}
83+
PATH_SUFFIXES eigen3 eigen
84+
)
85+
endif(NOT EIGEN3_INCLUDE_DIR)
86+
87+
if(EIGEN3_INCLUDE_DIR)
88+
_eigen3_check_version()
89+
endif(EIGEN3_INCLUDE_DIR)
90+
91+
include(FindPackageHandleStandardArgs)
92+
find_package_handle_standard_args(Eigen3 DEFAULT_MSG EIGEN3_INCLUDE_DIR EIGEN3_VERSION_OK)
93+
94+
mark_as_advanced(EIGEN3_INCLUDE_DIR)
95+
96+
endif(EIGEN3_INCLUDE_DIR)
97+

script/installation/packages.sh

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,10 @@ function install_protobuf3.4.0() {
4848
if [ "$DISTRIB" == "ubuntu" ]
4949
then
5050
sudo apt-get --yes --force-yes remove --purge libprotobuf-dev protobuf-compiler
51-
elif [ "$DISTRIB" == "fedora" ]
51+
elif [ "$DISTRIB" == "fedora" ]
5252
then
5353
sudo dnf -q remove -y protobuf protobuf-devel protobuf-compiler
54-
else
54+
else
5555
echo "Only Ubuntu and Fedora is supported currently!"
5656
return 0
5757
fi
@@ -72,7 +72,8 @@ function install_tf() {
7272
TARGET_DIRECTORY="/usr/local"
7373
# Install Tensorflow Python Binary
7474
sudo -E pip3 install --upgrade pip
75-
sudo -E pip3 install --upgrade tensorflow==${TF_VERSION}
75+
# Related issue: https://github.com/pypa/pip/issues/3165
76+
sudo -E pip3 install tensorflow==${TF_VERSION} --upgrade --ignore-installed six
7677

7778
# Install C-API
7879
TFCApiURL="https://storage.googleapis.com/tensorflow/libtensorflow/${TFCApiFile}"
@@ -161,7 +162,8 @@ if [ "$DISTRO" = "UBUNTU" ]; then
161162
libtool \
162163
make \
163164
g++ \
164-
ant \
165+
libeigen3-dev \
166+
ant \
165167
unzip
166168
# Install version of protobuf needed by C-API
167169
install_protobuf3.4.0 "ubuntu"
@@ -194,7 +196,8 @@ elif [ "$DISTRO" = "DEBIAN OS" ]; then
194196
llvm-dev \
195197
libedit-dev \
196198
postgresql-client \
197-
libtbb-dev
199+
libtbb-dev \
200+
libeigen3-dev
198201

199202
## ------------------------------------------------
200203
## FEDORA
@@ -239,7 +242,7 @@ elif [[ "$DISTRO" == *"FEDORA"* ]]; then
239242
automake \
240243
libtool
241244
# Install version of protobuf needed by C-API
242-
install_protobuf3.4.0 "fedora"
245+
install_protobuf3.4.0 "fedora"
243246
# Install tensorflow
244247
install_tf "$TFCApiFile" "$TF_VERSION" "$LinkerConfigCmd"
245248

@@ -343,6 +346,7 @@ elif [ "$DISTRO" = "DARWIN" ]; then
343346
brew install wget
344347
brew install python
345348
brew upgrade python
349+
brew install eigen
346350
# Brew installs correct version of Protobuf(3.5.1 >= 3.4.0)
347351
# So we can directly install tensorflow
348352
install_tf "$TFCApiFile" "$TF_VERSION" "$LinkerConfigCmd"

src/CMakeLists.txt

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,6 @@ add_subdirectory(${PROJECT_SOURCE_DIR}/third_party/libpg_query/ libpg_query.a)
3636

3737
##################################################################################
3838

39-
# --[ tensorflow
40-
# Generate essential model files
41-
set(MODEL_GEN_DIR ${CMAKE_CURRENT_LIST_DIR}/brain/modelgen)
42-
set(MODEL_GEN_PY ${MODEL_GEN_DIR}/model_generator.py)
43-
set(MODEL_GEN_SETTINGS ${MODEL_GEN_DIR}/settings.json)
44-
set(MODEL_GEN_COMMAND python3 ${MODEL_GEN_PY} ${MODEL_GEN_SETTINGS} ${MODEL_GEN_DIR})
45-
46-
message(STATUS "Tensorflow models being generated")
47-
execute_process(COMMAND ${MODEL_GEN_COMMAND}
48-
RESULT_VARIABLE RETURN_VALUE)
49-
50-
if (NOT RETURN_VALUE EQUAL 0)
51-
message(FATAL_ERROR "Failed to generate tensorflow models.")
52-
endif()
53-
54-
##################################################################################
55-
5639
# --[ Peloton library
5740

5841
# creates 'srcs' lists

src/brain/modelgen/LSTM.pb

-229 KB
Binary file not shown.

src/brain/modelgen/LSTM.py

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
#===----------------------------------------------------------------------===#
2+
#
3+
# Peloton
4+
#
5+
# LSTM.py
6+
#
7+
# Identification: src/brain/modelgen/LSTM.py
8+
#
9+
# Copyright (c) 2015-2018, Carnegie Mellon University Database Group
10+
#
11+
#===----------------------------------------------------------------------===#
12+
13+
import tensorflow as tf
14+
import functools
15+
import os
16+
import argparse
17+
18+
def lazy_property(function):
19+
attribute = '_cache_' + function.__name__
20+
21+
@property
22+
@functools.wraps(function)
23+
def decorator(self):
24+
if not hasattr(self, attribute):
25+
setattr(self, attribute, function(self))
26+
return getattr(self, attribute)
27+
28+
return decorator
29+
30+
class LSTM:
31+
32+
def __init__(self, ntoken, ninp, nhid, nlayers, lr=0.001,
33+
dropout_ratio=0.5, clip_norm = 0.5, **kwargs):
34+
"""
35+
:param ntoken: #features(input to encoder)
36+
:param ninp: input_size to LSTM(output of encoder)
37+
:param nhid: hidden layers in LSTM
38+
:param nlayers: number of layers
39+
:param dropout: dropout rate
40+
"""
41+
tf.reset_default_graph()
42+
self.data = tf.placeholder(tf.float32, [None, None, ntoken], name="data_")
43+
self.target = tf.placeholder(tf.float32, [None, None, ntoken], name="target_")
44+
self._ntoken = ntoken
45+
self._ninp = ninp
46+
self._nhid = nhid
47+
self._nlayers = nlayers
48+
# Setting to defaults known to work well
49+
self._lr = tf.placeholder_with_default(lr, shape=None,
50+
name="learn_rate_")
51+
self._dropout_ratio = tf.placeholder_with_default(dropout_ratio, shape=None,
52+
name="dropout_ratio_")
53+
self._clip_norm = tf.placeholder_with_default(clip_norm, shape=None,
54+
name="clip_norm_")
55+
self.tf_init = tf.global_variables_initializer
56+
self.prediction
57+
self.loss
58+
self.optimize
59+
60+
61+
@staticmethod
62+
def stacked_lstm_cell(num_cells, hid_units, dropout):
63+
cells = []
64+
for i in range(num_cells):
65+
cells.append(tf.nn.rnn_cell.DropoutWrapper(tf.nn.rnn_cell.LSTMCell(hid_units),
66+
output_keep_prob=dropout,
67+
variational_recurrent=False,
68+
dtype=tf.float32))
69+
return tf.nn.rnn_cell.MultiRNNCell(cells)
70+
71+
@lazy_property
72+
def prediction(self):
73+
net = self.data
74+
kernel_init = tf.random_normal_initializer()
75+
with tf.name_scope("input_linear_layer"):
76+
net_shape = tf.shape(net)
77+
bsz = net_shape[0]
78+
bptt = net_shape[1]
79+
net = tf.reshape(self.data, [-1, self._ntoken])
80+
net = tf.layers.dense(net, self._ninp,
81+
activation=tf.nn.leaky_relu,
82+
kernel_initializer=kernel_init)
83+
net = tf.reshape(net, [bsz, bptt, self._ninp])
84+
with tf.name_scope("stacked_lstm_cell"):
85+
stacked_lstm_cell = self.stacked_lstm_cell(self._nlayers,
86+
self._nhid,
87+
self._dropout_ratio)
88+
# If GPU is present, should use highly optimized CudnnLSTMCell
89+
net, _ = tf.nn.dynamic_rnn(stacked_lstm_cell,
90+
net, dtype=tf.float32,
91+
time_major=False)
92+
with tf.name_scope("output_linear_layer"):
93+
net = tf.reshape(net, [-1, self._nhid])
94+
net = tf.layers.dense(net, self._ntoken,
95+
activation=tf.nn.leaky_relu,
96+
kernel_initializer=kernel_init)
97+
net = tf.reshape(net, [bsz, bptt, -1], name="pred_")
98+
return net
99+
100+
@lazy_property
101+
def loss(self):
102+
loss = tf.reduce_mean(tf.squared_difference(self.target, self.prediction), name='lossOp_')
103+
return loss
104+
105+
@lazy_property
106+
def optimize(self):
107+
params = tf.trainable_variables()
108+
gradients = tf.gradients(self.loss, params)
109+
clipped_gradients, _ = tf.clip_by_global_norm(
110+
gradients, self._clip_norm)
111+
optimizer = tf.train.AdamOptimizer(learning_rate=self._lr)
112+
return optimizer.apply_gradients(zip(clipped_gradients,
113+
params), name="optimizeOp_")
114+
115+
def write_graph(self, dir):
116+
fname = "{}.pb".format(self.__repr__())
117+
abs_path = os.path.join(dir, fname)
118+
if not os.path.exists(abs_path):
119+
tf.train.write_graph(tf.get_default_graph(),
120+
dir, fname, False)
121+
122+
123+
def __repr__(self):
124+
return "LSTM"
125+
126+
def main():
127+
parser = argparse.ArgumentParser(description='LSTM Model Generator')
128+
129+
130+
parser.add_argument('--nfeats', type=int, default=3, help='Input feature length(input to encoder/linear layer)')
131+
parser.add_argument('--nencoded', type=int, default=20, help='Encoded feature length(input to LSTM)')
132+
parser.add_argument('--nhid', type=int, default=20, help='Number of LSTM Hidden units')
133+
parser.add_argument('--nlayers', type=int, default=2, help='Number of LSTM layers')
134+
parser.add_argument('--lr', type=float, default=0.001, help='Learning rate')
135+
parser.add_argument('--dropout_ratio', type=float, default=0.5, help='Dropout ratio')
136+
parser.add_argument('--clip_norm', type=float, default=0.5, help='Clip Norm')
137+
parser.add_argument('graph_out_path', type=str, help='Path to write graph output', nargs='+')
138+
args = parser.parse_args()
139+
model = LSTM(args.nfeats, args.nencoded, args.nhid,
140+
args.nlayers, args.lr, args.dropout_ratio,
141+
args.clip_norm)
142+
model.tf_init()
143+
model.write_graph(' '.join(args.graph_out_path))
144+
145+
if __name__ == '__main__':
146+
main()

0 commit comments

Comments
 (0)