369 строки
13 KiB
Bash
Executable File
369 строки
13 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# Copyright (c) Microsoft. All rights reserved.
|
|
#
|
|
# Licensed under the MIT license. See LICENSE.md file in the project root
|
|
# for full license information.
|
|
# ==============================================================================
|
|
#
|
|
# TODO --math-library support on Windows
|
|
|
|
# Setting some default values
|
|
BUILD=1
|
|
RUN=1
|
|
CLEAN_AFTER=0
|
|
CLEAN_BEFORE=0
|
|
RANDOM_OUTPUT=0
|
|
CODE_COVERAGE=no
|
|
FLAVORS="debug:release"
|
|
TARGETS="cpu:gpu"
|
|
MATH_LIBRARY="mkl"
|
|
TESTTARGETS="cpu:gpu"
|
|
EXTRA_CONFIGURE_OPTIONS=
|
|
|
|
# parsing command line arguments:
|
|
while [[ $# > 0 ]]
|
|
do
|
|
key="$1"
|
|
|
|
case $key in
|
|
-h|--help)
|
|
echo "Usage: build-and-test [options]"
|
|
echo "Options:"
|
|
echo " -q|--quiet-build - redirect build output to file"
|
|
echo " -r|--run-only - elides build step, runs the binaries that have already been built"
|
|
echo " -b|--build-only - just build, do not run"
|
|
echo " -f|--flavors <flavor1:flavor2...> - which flavor to build (by default $FLAVORS)"
|
|
echo " -t|--targets <target1:target2...> - which target to build (by default $TARGETS)"
|
|
echo " -m|--math-library <mathlibrary> - which math library to build with (by default $MATH_LIBRARY)"
|
|
echo " -tt|--test-targets <testtarget1:testtarget2...> - which target to test (by default $TESTTARGETS)"
|
|
echo " -cc|--code-coverage - build with support for code coverage (gcov)"
|
|
echo " -cb|--clean-build - clean up the enlistment binaries before build"
|
|
echo " -cba|--clean-build-after - clean up the enlistment binaries after build"
|
|
echo " -rnd|--random-output-suffix - add random suffix to output directory"
|
|
echo " -o|--output-directory <output_dir> - specify output directory to use (by default those will be in <cntk_root>.run-<operating_system>)"
|
|
echo " -x|--extra-configure-options <options> - extra options to pass to configure"
|
|
echo "The root directory used to build and run CNTK is hosts the Scripts directory that contains this script"
|
|
exit 1
|
|
;;
|
|
-q|--quiet)
|
|
QUIET_BUILD=1
|
|
;;
|
|
-r|--run-only)
|
|
BUILD=0
|
|
RUN=1
|
|
;;
|
|
-rnd|--random-output-suffix)
|
|
RANDOM_OUTPUT=1
|
|
;;
|
|
-b|--build-only)
|
|
BUILD=1
|
|
RUN=0
|
|
;;
|
|
-cb|--clean-build)
|
|
CLEAN_BEFORE=1
|
|
BUILD=1
|
|
;;
|
|
-cba|--clean-build-after)
|
|
CLEAN_AFTER=1
|
|
BUILD=1
|
|
;;
|
|
-f|--flavors)
|
|
FLAVORS="${2,,}"
|
|
shift # past argument
|
|
;;
|
|
-t|--targets)
|
|
TARGETS="${2,,}"
|
|
shift # past argument
|
|
;;
|
|
-m|--math-library)
|
|
case ${2,,} in
|
|
mkl)
|
|
MATH_LIBRARY_OPTION="--with-mkl=$MKL_PATH"
|
|
;;
|
|
mkl-sequential)
|
|
MATH_LIBRARY_OPTION="--with-mkl-sequential=$MKL_PATH"
|
|
;;
|
|
*)
|
|
echo Unknown math library $MATH_LIBRARY
|
|
exit 1
|
|
;;
|
|
esac
|
|
shift # past argument
|
|
;;
|
|
-tt|--test-targets)
|
|
TESTTARGETS="${2,,}"
|
|
shift # past argument
|
|
;;
|
|
-cc|--code-coverage)
|
|
CODE_COVERAGE=yes
|
|
;;
|
|
-x|--extra-configure-options)
|
|
EXTRA_CONFIGURE_OPTIONS="$2"
|
|
shift # past argument
|
|
;;
|
|
-o|--output-directory)
|
|
OUTPUT_DIR="$2"
|
|
shift # past argument
|
|
;;
|
|
*)
|
|
echo Unknown option $key
|
|
exit 1
|
|
;;
|
|
esac
|
|
shift # past argument or value
|
|
done
|
|
|
|
# Step 0 -- Validate all necessary prerequisites and check for incompatible options
|
|
# It is possible to use this script on Windows to build CNTK
|
|
# from Cygwin window with Visual C++ environment loaded.
|
|
# In that case OS environment variable will be set and we
|
|
# can use it to differentiate from Linux.
|
|
if [[ $CLEAN_BEFORE == 1 && $RUN == 1 && $BUILD == 0 ]]; then
|
|
echo "============ ERROR: Incompatible options RUN and CLEAN_BEFORE set without BUILD ============"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ $OS == "Windows_NT" && $OSTYPE == "cygwin" ]]; then
|
|
DEBUG_DIR=Debug
|
|
RELEASE_DIR=Release
|
|
PREFIX_DIR=x64
|
|
BIN_NAME=CNTK.exe
|
|
BUILD_OS="windows"
|
|
|
|
if [[ $VS120COMNTOOLS == "" ]]; then
|
|
echo "============ Visual Studio 12.0 environment not properly setup or VS not installed ============"
|
|
echo "============ Please find and run the appropriate vcvarsall.bat script ============"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "${TARGETS,,}" =~ "1bitsgd" && "${TARGETS,,}" =~ "gpu" ]]; then
|
|
echo "============ Cannot specify both GPU and 1bit-SGD as targets, please choose one ============"
|
|
exit 1
|
|
fi
|
|
|
|
elif [[ $OSTYPE == "linux-gnu" ]]; then
|
|
DEBUG_DIR=build/$TARGET/debug
|
|
RELEASE_DIR=build/$TARGET/release
|
|
PREFIX_DIR=
|
|
# Make sure no dependencies on current directory
|
|
BIN_NAME=bin/cntk
|
|
MAKEFILE=Makefile
|
|
BUILD_OS="linux"
|
|
else
|
|
echo "============ ERROR: Unsupported OS ============"
|
|
echo "============ Script supports only building from Linux and Windows through Cygwin ============"
|
|
exit 1
|
|
fi
|
|
|
|
# Step 1 -- Prepare temporary folders and files, tweak settings if necessary
|
|
|
|
# Get to the root path from which we know how to build and run
|
|
SCRIPT=`readlink -f $0`
|
|
SCRIPT_DIR=`dirname $SCRIPT`
|
|
CNTK_ROOT=`dirname $SCRIPT_DIR`
|
|
|
|
# Setup the output directory
|
|
if [[ $OUTPUT_DIR == "" ]]; then
|
|
OUTPUT_DIR="$CNTK_ROOT/.run-$BUILD_OS"
|
|
fi
|
|
|
|
# Add random number at the end of the output directory to prevent overwriting previous results
|
|
if [[ $RANDOM_OUTPUT == 1 ]]; then
|
|
OUTPUT_DIR="$OUTPUT_DIR-$RANDOM"
|
|
fi
|
|
|
|
echo "============ Creating CNTK temp directory in $OUTPUT_DIR ============"
|
|
mkdir -p $OUTPUT_DIR || exit $?
|
|
|
|
CONF_FILE="$OUTPUT_DIR/Simple.cntk"
|
|
BUILD_FILE="$OUTPUT_DIR/Build"
|
|
RUN_FILE="$OUTPUT_DIR/Result"
|
|
|
|
if ! [[ -d "$CNTK_ROOT/Source" ]]; then
|
|
echo "============ ERROR: Build script located in the wrong directory ($SCRIPT_DIR) ============"
|
|
exit 1
|
|
fi
|
|
|
|
cd $CNTK_ROOT
|
|
|
|
if ! [[ -f $CONF_FILE ]]; then
|
|
cp Examples/Other/Simple2d/Config/Simple.cntk $CONF_FILE || exit $?
|
|
|
|
# This chmod is necessary due to restrictive Cygwin interpretation of Windows permissions.
|
|
# Cygwin interprets Windows permissions as ----rwx---, which lacks read permissions for user.
|
|
chmod a+r $CONF_FILE || exit $?
|
|
fi
|
|
|
|
if [[ $QUIET_BUILD == 1 ]]; then
|
|
echo "============ WARNING: You have selected quiet build. All build output will be placed in ($OUTPUT_DIR) ============"
|
|
fi
|
|
|
|
# Initialize lists of flavors and targets
|
|
flavorArray=(${FLAVORS//:/ })
|
|
targetArray=(${TARGETS//:/ })
|
|
testTargetArray=(${TESTTARGETS//:/ })
|
|
|
|
# Step 2 -- Build the project for all requested flavors and targets
|
|
if [[ $BUILD == 1 ]]; then
|
|
for FLAVOR in "${flavorArray[@]}"
|
|
do
|
|
for TARGET in "${targetArray[@]}"
|
|
do
|
|
echo "============ Building CNTK $TARGET/$FLAVOR (clean=$CLEAN_BEFORE) ============"
|
|
|
|
# Our make is too noisy right now and it is difficult to spot
|
|
# issues from stdout and stderr. In the quiet mode these are
|
|
# redirected to a file where they could be examined after the fact
|
|
if [[ $QUIET_BUILD == 1 ]]; then
|
|
exec 6>$BUILD_FILE.$FLAVOR.out || exit $?
|
|
exec 7>$BUILD_FILE.$FLAVOR.err || exit $?
|
|
else
|
|
exec 6>&1 || exit $?
|
|
exec 7>&2 || exit $?
|
|
fi
|
|
|
|
if [[ $OS == "Windows_NT" ]]; then
|
|
OneBitSGDOPT=/property:CNTK_ENABLE_1BitSGD=
|
|
if [[ $TARGET == "cpu" ]]; then
|
|
CONFIGURATION=${FLAVOR}_CpuOnly
|
|
else
|
|
CONFIGURATION=${FLAVOR}
|
|
if [[ $TARGET == "1bitsgd" ]]; then
|
|
OneBitSGDOPT=/property:CNTK_ENABLE_1BitSGD=true
|
|
fi
|
|
fi
|
|
|
|
if [[ $CLEAN_BEFORE == 1 ]]; then
|
|
msbuild.exe /nologo /verbosity:m /property:Configuration=$CONFIGURATION /t:Clean 1>&6 2>&7 || exit $?
|
|
fi
|
|
msbuild.exe /nologo /verbosity:m /m /property:Configuration=$CONFIGURATION $OneBitSGDOPT 1>&6 2>&7 || exit $?
|
|
else
|
|
OneBitSGDOPT=no
|
|
BUILD_DIR=build/$TARGET/$FLAVOR
|
|
if [[ $TARGET == "cpu" ]]; then
|
|
CUDAOPT=no
|
|
else
|
|
CUDAOPT=yes
|
|
if [[ $TARGET == "1bitsgd" ]]; then
|
|
OneBitSGDOPT=yes
|
|
fi
|
|
fi
|
|
./configure --with-build-top=$BUILD_DIR ${MATH_LIBRARY_OPTION} --with-buildtype=$FLAVOR --cuda=$CUDAOPT --with-code-coverage=$CODE_COVERAGE --1bitsgd=$OneBitSGDOPT $EXTRA_CONFIGURE_OPTIONS
|
|
if [[ $CLEAN_BEFORE == 1 ]]; then
|
|
make -C $BUILD_DIR -f $MAKEFILE clean 1>&6 2>&7 || exit $?
|
|
fi
|
|
make -C $BUILD_DIR -j `nproc` -f $MAKEFILE 1>&6 2>&7 || exit $?
|
|
|
|
fi
|
|
if [[ $QUIET_BUILD == 1 ]]; then
|
|
chmod a+r $BUILD_FILE.*
|
|
fi
|
|
done
|
|
done
|
|
fi
|
|
|
|
# Step 3 -- Run the project tests, both debug and release, if requested
|
|
if [[ $RUN == 1 ]]; then
|
|
|
|
cd $PREFIX_DIR
|
|
echo "============ cp Examples/Other/Simple2d/Config/Simple.cntk $CONF_FILE ============"
|
|
echo "============ cd $CNTK_ROOT/Examples/Other/Simple2d/Data ============"
|
|
|
|
for FLAVOR in "${flavorArray[@]}"
|
|
do
|
|
for TARGET in "${targetArray[@]}"
|
|
do
|
|
for TESTTARGET in "${testTargetArray[@]}"
|
|
do
|
|
# Determine how to set the deviceId parameter in the configuration.
|
|
# 0 will pick the first GPU (or fail. -1 will pick the CPU.
|
|
if [[ $TESTTARGET == gpu ]]; then
|
|
DEVICE_ID=0
|
|
else
|
|
DEVICE_ID=-1
|
|
fi
|
|
|
|
if [[ $TESTTARGET == gpu && $TARGET == cpu ]]; then
|
|
# CPU-only builds cannot run GPU test targets
|
|
continue;
|
|
fi
|
|
|
|
if [[ $OSTYPE == "linux-gnu" ]]; then
|
|
FLAVOR_DIR=build/$TARGET/$FLAVOR
|
|
else
|
|
if [[ $FLAVOR == "debug" ]]; then
|
|
FLAVOR_DIR="$DEBUG_DIR"
|
|
else
|
|
FLAVOR_DIR="$RELEASE_DIR"
|
|
fi
|
|
if [[ $TARGET == cpu ]]; then
|
|
FLAVOR_DIR="${FLAVOR}_CpuOnly"
|
|
fi
|
|
fi
|
|
OUT_FILE="$RUN_FILE.$FLAVOR.$TARGET.$TESTTARGET.out"
|
|
|
|
BIN_PATH=$CNTK_ROOT/$PREFIX_DIR/$FLAVOR_DIR/$BIN_NAME
|
|
if ! [[ -f $BIN_PATH ]]; then
|
|
echo "============ ERROR: CNTK did not build properly for $TARGET/$FLAVOR ============"
|
|
echo "Missing file: $BIN_PATH"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ $OS == "Windows_NT" ]]; then
|
|
echo "============ Running $BIN_PATH configFile=`cygpath -w $CONF_FILE` for $TARGET/$FLAVOR (on $TESTTARGET) ============"
|
|
else
|
|
echo "============ Running $BIN_PATH configFile=$CONF_FILE for $TARGET/$FLAVOR (on $TESTTARGET) ============"
|
|
fi
|
|
echo "============ output in ($OUT_FILE) ============"
|
|
cd $CNTK_ROOT/Examples/Other/Simple2d/Data
|
|
rm -rf "$OUTPUT_DIR/Models"
|
|
if [[ $OS == "Windows_NT" ]]; then
|
|
# We have to use cygpath on Windows to modify the file paths into the format readable by cntk.
|
|
time $BIN_PATH configFile="`cygpath -w $CONF_FILE`" deviceId=$DEVICE_ID OutputDir="`cygpath -w $OUTPUT_DIR`" &>$OUT_FILE || exit $?
|
|
else
|
|
time $BIN_PATH configFile=$CONF_FILE deviceId=$DEVICE_ID OutputDir="$OUTPUT_DIR" &>$OUT_FILE || exit $?
|
|
fi
|
|
chmod a+r $RUN_FILE.*
|
|
|
|
# Check if execution was successful
|
|
grep -q "Using ${TESTTARGET^^}" "$OUT_FILE" || {
|
|
echo "============ ERROR: Run output (in $OUT_FILE) did not contain information about target device ($TESTTARGET) ============"
|
|
exit 1
|
|
}
|
|
|
|
grep -q "EXCEPTION" "$OUT_FILE" && {
|
|
echo "============ ERROR: Run output in ($OUT_FILE) contains exceptions ============"
|
|
grep "EXCEPTION" "$OUT_FILE"
|
|
exit 1
|
|
}
|
|
done
|
|
done
|
|
done
|
|
fi
|
|
|
|
# Step 5 -- Optionally clean after builds and tests
|
|
if [[ $CLEAN_AFTER == 1 ]]; then
|
|
cd $CNTK_ROOT
|
|
for FLAVOR in "${flavorArray[@]}"
|
|
do
|
|
for TARGET in "${targetArray[@]}"
|
|
do
|
|
echo "============ Cleaning up CNTK $TARGET/$FLAVOR ============"
|
|
if [[ $OS == "Windows_NT" ]]; then
|
|
if [[ $TARGET == "cpu" ]]; then
|
|
CONFIGURATION=${FLAVOR}_CpuOnly
|
|
else
|
|
CONFIGURATION=${FLAVOR}
|
|
fi
|
|
msbuild.exe /nologo /verbosity:m /property:Configuration=$CONFIGURATION /t:clean 1>&6 2>&7 || exit $?
|
|
else
|
|
make -C build/$TARGET/$FLAVOR -f $MAKEFILE clean 1>&6 2>&7 || exit $?
|
|
fi
|
|
done
|
|
done
|
|
rm -rf "$OUTPUT_DIR"
|
|
fi
|
|
|
|
echo "============ Build and test of CNTK was successful! ============"
|