You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mxnet.apache.org by re...@apache.org on 2018/08/04 04:41:40 UTC

[incubator-mxnet] branch subgraph updated (9c837b0 -> 6acf6cc)

This is an automated email from the ASF dual-hosted git repository.

reminisce pushed a change to branch subgraph
in repository https://gitbox.apache.org/repos/asf/incubator-mxnet.git.


    omit 9c837b0  [DO NOT REVIEW] Fix bug of eliminating cycles (#11907)
    omit 8367708  Make subgraph var node name unique (#11876)
    omit 6fe9db2  Fix duplicate entry bugs (#11767)
    omit 9567bd7  Graph partitioner and subgraph op (#11251)
     add 7a83a75  [MXNET-555] Add subgraph storage type inference to CachedOp  (#11306)
     add bb105a1  [MXNET-405] Add 2 new pipelines to the Official CI and run nightly tests.  (#10827)
     add afc1496  [WIP]Update resnet pretrained models (#11327)
     add d6813ef  Fix typo in lrn (#11347)
     add 529ee85  [MXNET-561] Add test coverage reporting (#11344)
     add 5550c0a  Fix issue of test_gru_bidirectional #11219 and add robust code (#11333)
     add 579e376  [MXNET-558] Fix 'AttributeError: '_thread._local' object has no attribute 'value'' on distributed processing applications (#11332)
     add 10100b8  Removing the stale links from docs/index.md (#11372)
     add adec280  flaky test disable test_ImageRecordIter_seed_augmentation temporarily (#11381)
     add 9b27262  Enable support for dense weight and sparse grad Adagrad updates (#11355)
     add 7d91602  [MXNET-533] MXNet-ONNX export (#11213)
     add 225f71f  [MXNET-538] Add XUnit test result publishing to windows (#11348)
     add cdb01fc  Don't fail storing test results if test suite got aborted (#11363) (#11391)
     add 619e4bd  Fix #11353 (#11360)
     add 72fa6a9  fix recordfile dataset with multi worker (#11370)
     add 21ff36b  Fix flaky test test_operator.test_binary_op due to numerical errors (#11259)
     add ed7e360  [MXNET-349] Histogram Operator (#10931)
     add e494cee  [MXNET-593] Adding 2 tutorials on Learning Rate Schedules (#11296)
     add 0538ad9  add vRNN and dropout (#11399)
     add e4bf646  [MXNET-551] Test CreateMKLDNNMem/CommitOutput (#11308)
     add 4db5a83  Fix bi-lstm-crf to update crf weights (#11375)
     add ced119b  Fix flaky test test_operator_gpu.test_batchnorm_with_type (#11396)
     add 99af59b  [MXNET-139] Tutorial for mixed precision training with float16 (#10391)
     add 7052720  [MXNET-559] Scripts for running the  Broken link checker job (#11340)
     add a4f4e76  Define build target for mkldnn lib build to fix 'make clean USE_MKMLDNN=1' issue (#11090)
     add 2885370  [MXNET-601] Fix caffe converter test (#11425)
     add ccc1237  Add license (#11433)
     add f848b3e  Update email notifications (#11432)
     add e8f52b3  [Nightly Tests] Sync with latest Dockerfile changes and Enable KV store test (#11358)
     add 8fde4b7  Fix symbolic example (#11428)
     add 645057b  Disable flaky tests (#11440)
     add a97a475  [MXNET-23] add README for test directory (#11390)
     add 4d3edd3  changes to rat excludes post 1.2.1 (#11454)
     add 2fe5144  [MXNET-602] [MXNET-603] Disabling a number of tests to improve CI stability. (#11422)
     add 515404a  [MXNET-605] Hotfix for USE_BLAS=mkl compile bug (#11449)
     add b73b7b8  [MXNET-606] Ppa retries in CI (#11461)
     add 1b69e4b  [MXNET-561] Retry submission of coverage report on 4xx, 5xxs (#11460)
     add a7d858d  lower learning rate (#11467)
     add dc291d3  Enable test_autograd_save_memory (#11437)
     add 52ce0c3  Replace PTB dataset to Sherlock Holmes  (#11435)
     add c6c04d4  Fix tensorboard.py #9743 (#11426)
     add f7a0025  Fix flaky test test_operator_gpu.test_spatial_transformer_with_type (#7645) (#11444)
     add 4cdc150  fix. (#11471)
     add 3ff7bf7  Update contrib.py (#11447)
     add 044afa3  [MXNET-312] Added Matthew's Correlation Coefficient to metrics (#10524)
     add 2594fca  Document AdaGrad eps as initial history accumulator value (#11392)
     add 36f2aae  support shared parameter in summary (#11379)
     add b344d89  fix record io augmentation speed (#11474)
     add f02e627  fix regex which processes RAT check output (#11476)
     add a4054cd  [MXNET-607] Fix the broken reported by the new BLC (#11465)
     add a0669d0  [Nightly Tests] Disable some nightly tests for installation guide (#11452)
     add 1d9096f  Update CODEOWNERS (#11416)
     add 7ce746f  Disable flaky test test_sequence_last (#11485)
     add 2509e0c  [MXNET-610] Disable flaky test test_sample_multinomial (#11488)
     add c84a2f6  [MXNET-564] Fix the Flaky test on arange (#11377)
     add 4511086  [MXNET-603] Disable flaky test test_hybrid_static_memory (#11486)
     add e4575ea  Fix typo in Dockerfile description. (#11354)
     add 48fbc72  Enable test_conv (#11490)
     add 39ca251  fix flaky test_sparse_dot and incorrect handling of empty sparse tensors (#11389)
     add ca60b94  [MXNET-537] add_n(dense, csr, dense) = dense and add_n([dense, csr, rsp]*, dense, [dense, csr, rsp]*) = dense on CPU & GPU (#11330)
     add af4a600  [MXNET-486] Create CPP test for concat MKLDNN operator (#11371)
     add fdf2283  [MXNET-612] Optimize RAT setup and move it into PR stage (#11492)
     add c74a8e1  Make MXNetError in Scala Not Private (#11491)
     add 275cd8e  update docs: deps using CI scripts and other clarifications (#11431)
     add 3a62200  support int64 data type in CSVIter (#11446)
     add ebfc16e  test for new int64 type in CSVIter (#11499)
     add e892301  [MXNET-517] add sample ratio for ROI Align (#11145)
     add 355de66  [MXNET-548] fixed path for auto_module_index.js (#11287)
     add f783a66  [MXNET-379] L1 Normalization (#11229)
     add 33022f8  [MXNET-382] Shape and Size Operator (#10889)
     add cca0883  MXNET-336 [Perl] Major Gluon update for Perl API. (#11414)
     add 806b41b  Update large word language model example (#11405)
     add 9a0099f  [MXNET-595] Install page not loading properly in Internet Explorer (#11404)
     add 7e5d88d  Disable flaky test test_conv in gluon (#11507)
     add b22ce0b  Disable test_norm (#11510)
     add 45a1040  Removing the test, as behavior varies with system arch (Intel vs AMD) (#11463)
     add 92900f0  rnn_cell little bug fixed (#11003)
     add 12709ac  new NER example: MXNET-321 (#10514)
     add 06a18ab  [MXNET-615] Fix for flaky test_svmoutput_with_type (#11505)
     add 8917318  Clojure Contrib Package (#11205)
     add 37c8165  Add licenses to clojure package (#11512)
     add 5627bc3  [MXNET-531] MNIST Examples for Scala new API (#11250)
     add cba2b03  add test for #11003 (#11511)
     add c5035b6  batchnorm falls back for sparse arrays. (#11473)
     add 568cbaf  Re-enable kvstore test  (#11519)
     add 84b9b41  Disable test_pooling_versions (#11518)
     add cb4d310  Add redundant R key servers. (#11489)
     add d34452b  Add fallback for codecov (#11524)
     add 6bdd922  Fix #11504. Division by zero in callback with very fast speed (#11521)
     add 555dc30  [MXNET-57] Android ARMv7 support (#11382)
     add d6a8ca7  handle the case that inputs and outputs of a graph share NDArrays (#11436)
     add 99ac2f5  Compile with LAPACK shared library (#11483)
     add 490e951  Fix flaky test 10380 (#11529)
     add defd544  Replace save_params and load_params with save_parameters and load_parameters (#11527)
     add 7c74d1f  [MXNET-210]give warning for variables with same name in graph visualization (#10429)
     add 030fbc3  [MXNET-432] Add Foreach (#11531)
     add 0ae38c7  Update block.py (#11532)
     add 34fafb4  Fix Flaky test test_multi_proposal_op as in #10186 (#11530)
     add e94146f  Move the auto-generation for the ndarray and symbol files to compile time (AOT) (#11534)
     add 552c715  updating installation info to have latest packages and more clarity (#11503)
     add 5df5f2e  Update block.py (#11540)
     add 40ae851  [MXNET-617] - Improve Clojure styles with cljfmt tools revise (#11537)
     add 815eb60  [MXNET-319] Javadoc fix (#11239)
     add 01f1457  [MXNET-565]change wget into java download (#11383)
     add 92f0c51  [MXNET-531] GAN MNIST Examples for Scala new API (#11547)
     add 9e681f2  [MXNET-531] Maven demo project (#11451)
     add eb4b66c  Profiler is already enabled by default in 1.2.0 (#11558)
     add e870890  [MXNET-594] Added Learning Rate Finder tutorial (#11304)
     add 19ac41d  Manually check node existence in CachedOp (#11545)
     add a4c8d97  Updating Scala IntelliJ tutorial & installation instructions (#11152)
     add 1ca6622  Fix typo in clojure project dependencies. (#11582)
     add 52dcb19  [MXNET-392] Support for a bunch of unary functions for csr matrices (#11559)
     add ef820c1  [MXNET-613] Upgrade jetpack to version 3.2.1 (#11494)
     add fc2acb0  Add path_suffixes for finding cudnn.lib (#11513)
     add dd954b4  fix flaky test (ran 50000 times locally) (#11595)
     add 9652b39  Fix scala maven repos (#11604)
     add c922547  Add CODEOWNERS (#11598)
     add 6924390  CMake 3.12 will not detect a variable as empty string (#11584)
     add 0d5ebe1  [MXNET-497] fix bugs in MKLDNN operators to handle the kAddTo request (#11129)
     add 459a891  ColorNormalizeAug now accepts mxnet NDArrays as well as stated (wrongly) in the documentation. (#11606)
     add 266de6b  Improve sparse pull performance for gluon trainer (#11429)
     add 53e8afd  Disable flaky test: gluon test_export (#11617)
     add 5ff9b92  fix nccl compilation (#11623)
     add 1e698d5  fix xml display bug (#11624)
     add 0bec94b  [MXNET-620]Fix flaky test batchnorm training (#11544)
     add 7a6e8de  [MXNET-624] Clojure Package Api Docs for the Website (#11574)
     add c792638  Fix flaky test:test_sample_multinomial (#11366)
     add 43ad56c  Add stable nrm2 Reducer (#11573)
     add d814733  Added query for cuDNN BN min. epsilon. Enabled choice of BN impl. for ONNX import (#11380)
     add f665c13  [MXNET-652] Allow for multi-context input to load gluon models from onnx (#11637)
     add 4ae0cd9  Fix for flaky keyserver keyserver.ubuntu.com. Fix #11601 (#11602)
     add b264f6f  Fix flaky test test_gluon.test_hybrid_static_memory_switching (#11577)
     add db5d350  Adding models to example list and ONNX API page (#11632)
     add 5798b6a  [example/sparse/factorization_machine/]add auc and fix the typo in re… (#10594)
     add 7dbbe59  Fix InferStorage for sparse fallback in FullyConnected (#11498)
     add d25fdb7  [MXNET-670] shape_array and size_array operator is non-differentiable (#11661)
     add ea24c1c  [MXNET-627] Fix Installation instructions for R bindings on Linux systems. (#11590)
     add b786ead  [MXNET-531] Integration Test for Scala (#11596)
     add 2dcb35e  Modernize Python 2 code to get ready for Python 3 (#11648)
     add 8240d3a  [CI] cleanup and script refinements (#11600)
     add e912314  New style exception for Python 3 (#11668)
     add 2fd7085  documentation enhancement for optimizers (#11657)
     add 5b63144  Fix build issue with USE_CUDNN=0 (#11470)
     add c766712  update rcnn example (#11373)
     add 6b2cbd4  xrange(10) --> range(10) for Python 3 (#11673)
     add 92366a9  Update README.md (#11677)
     add 32d298b  [MXNET-323] Improve performance of broadcast ops backward pass (#11252)
     add f22ae1d  Fix TabError for Python 3 (#11669)
     add d611037  Some Python 3 fixes in ./tools (#11672)
     add 5b4d528  fix batchnorm problem with sparse matrices when fix_gamma=True (#11656)
     add 238a497  Disable batchnorm (#11746)
     add d5c5006  Update benchmark_score.py (#11679)
     add 0bb6e2b  Speed up GPU Windows builds in CI (#11745)
     add daa2a43  Revert "Some Python 3 fixes in ./tools (#11672)" (#11750)
     add de2edc7  MXNET-650 [Perl] Gluon ModelZoo, Gluon examples  (#11642)
     add 11cd73f  Fix dist kvstore for trainer and flaky dist kvstore test (#11633)
     add 3ae4331  [MXNET-614] Adding Synchronized Batch Normalization (#11502)
     add 444775b  Remove dead code in Jenkinsfile (#11762)
     add 01cba7b  Fix R installation in CI (#11761)
     add e77fa04  fix R quick install instructions (#11755)
     add 3ea67a7  fix eps value for test_batchnorm_fallback (#11759)
     add 2fdd902  Fix force_addtakegrad (#11764)
     add 5495e2a  [MXNET-531] CNN Examples for Scala new API (#11292)
     add f622a99  updating image reference and fixing additional text (#11754)
     add f235605  Fix nightly R installation (#11768)
     add c792c9f  add arange fix (#11766)
     add 716df26  add arange fix (#11766)
     add bcf4245  Some Python 3 fixes in ./example (#11671)
     add b531cbc  MXNet ONNX export - Dot op support (#11771)
     add e70f6ff  onnx split op import (#11593)
     add 007c288  [MXNET-622] Add timeout for BLC (#11554)
     add 9264755  Docs build improvements (#11670)
     add fe567f2  added new users list info; sync info with channels page (#11782)
     add ede98e5  [MXNET-682] Disable Caffe import integration test (#11781)
     add e994a35  fix rnn layer save (#11776)
     add 3051c49  [MXNET-381] Enhancement of take operator (#11326)
     add bcf3a88  fix rnn api docs (#11788)
     add ab30cf8  [MXNET-8230] test_operator_gpu.test_rms fails (#11749)
     add 4a02bde  Some Python 3 fixes in ./tools again (#11757)
     add 6abfc70  NPE in BucketingModule when providedLabel of DataBatch is not set (#11790)
     add ae8b84c  Update Scala-MXNet install instructions (#11787)
     add 896271b  fix test_countsketch flakiness (#11780)
     add 072dd5a  [MXNET-531] Custom Operator Example for Scala (#11401)
     add 904052d  fix BucketSentenceIter bug related to #11430 (#11580)
     add c2a1a7c  fix bug when prefetch_buffer=1 (#11793)
     add 039e68a  Disable kvstore test (#11798)
     add 6d927d1  [MXNET-681] Add retry mechanism for the docker build stage (#11779)
     add 1240577  Use feature detection in base.py (#11803)
     add 80b7715  Update documentation for count_tokens_from_str (#11800)
     add 54632bc  [MXNET-626] Add while_loop (#11566)
     add 4b8ab63  MXNet docs change for 1.2.1 release (#11791)
     add 1031fe1  [MXNET-600][Scala] NDArray auto-collector (#11751)
     add 9b30af2  enable CPU kernel for all RNN layer forward (#11807)
     add bbcf083  Refactor armv8 builds and add to CI (#11579)
     add ee40f7c  Fix broken website build pipeline (#11813)
     add d86f954  Initial commit (#11823)
     add b1f2f44  [MXNET-560] Add temperature parameter in Softmax operator (#11466)
     add f15b1b8  Added the diag() operator (#11643)
     add 83ecf2d  Adding missing optimizers that use momentum. (#11826)
     add 2d7166f  Add trove classifiers for PyPI page (#11818)
     add 0147388   Some Python 3 fixes in ./tests (#11799)
     add 61a7695  New ecosystem website page (#11528)
     add b16f875  [MXNET-524] Broadcast like operator (#11820)
     add 1242769  detailed doc about global pool layers in Gluon (#11832)
     add 95de767  fix for bug #10868: _backward_softsign activation is incorrect (#11827)
     add cdb1297  [MXNET-489] MKLDNN Pool test (#11608)
     add e14b575  updated docs and hashes for vgg16,16_bn,19,19_bn (#11830)
     add 11b69f2  Flaky: Disabled broadcast_mod unit test (#11845)
     add 6798703  fix a bug in CachedOp. (#11675)
     add e80c89f  add link changes (#11828)
     add 049d048  [MXNET-531] improvement of adding source.jar to assembly (#11681)
     add 60b6ab6  Use new Symbol APIs in Profiler example (#11477)
     add 7c1a49b  Updating MultiTask example to use new infer api and adding test for CI (#11605)
     add a94fcf9  [MXNET-319] Reduce Scala Warning messages (#11789)
     add 65fee98  support 1D inputs in leaky relu (#11850)
     add b4156da  Update doc examples for MCC (#11852)
     add 38282e9  [MXNET-599] Partial shape infer for Slice (#11406)
     add 74d6692  Fix spatial transformer op (#11806)
     add 4bb141d  [MXNET-684] Add `cond` operator (#11760)
     add 55fef30  [MXNET-688] Fix quantization divide by zero errors (#11833)
     add f407345  [MXNET-645] Add flakiness checker (#11572)
     add 8f4b092  Enable control flow test (#11869)
     add 64d2e8b  [MXAPPS-581] Nightly Straight Dope tests. (#11814)
     add fe07d50  [MXNET-331] Single machine All Reduce Topology-aware Communication (Updated) (#11591)
     add fa935a8  Fix file name creation for Windows (#11765)
     add 8a21a06  update vgg pretrained model (#11860)
     add 07a9977  Add verify_ssl option to gluon.utils.download (#11546)
     add 424fafe  [MXNET-710] Change POM files to be able to regularly publish to Apache Release & Maven Central Repo (#11862)
     add 06f4ec7  Enable three retries for Docker build commands (#11877)
     add 0b8b939  Avoid Division by Zero (#11397)
     add fe1c7ab  making AddTakeGrad as default for backward of embedding and take to avoid nan (#11795)
     add be47870  [MXNET-563] Refactor R optimizers to fix memory leak (#11374)
     add 832a5fb  Add logistic regression tutorial (#11651)
     add 7cd01ff  Re-enabling randomized test_operator/test_operator_gpu.test_dot (#11888)
     add 302aae3  Fix non-determinism of dot(csr.T, dns) = dns with tests (#11825)
     add f5b95b0  Support integer type in ImageIter (#11864)
     add c13ce5c  [MXNET-378] Adding depth_to_space and space_to_depth operator(Updated) (#11587)
     add 2bddf6f  Fix mxnet ctc_loss bug (#11834)
     add 4bbf15c  [MXNET-344] Add more operators to onnx import (#11856)
     add a8c8737  make skiptest work (#11889)
     add bd3fc88  Fix flaky test test_deconvolution (#11630)
     add 011a0dc  Remove fixed seed for test_sparse_nd_save_load (#11920)
     add 196468d  Corrections to profiling tutorial (#11887)
     add 54ebc5d  Fix image classification scripts and Improve Fp16 tutorial (#11533)
     add ab5242c  [MXNET-711] Website build and version dropdown update (#11892)
     add 6372037  [MXAPPS-581] Fixes for broken Straight Dope tests. (#11923)
     add 83ae3a3  Disable flaky test: test_spatial_transformer_with_type (#11930)
     add 2cc5a42  Add linux and macos MKLDNN Building Instruction (#11049)
     add b2fd3b1  [MXNET-531] Add download util (#11866)
     add 024b5a9  [MXNET-11241] Avoid use of troublesome cudnnFind() results when grad_req='add' (#11338)
     add 478b4a1  Improving documentation and error messages for Async distributed training with Gluon (#11910)
     add 815f42d  [MXNET-641] fix R windows install docs (#11805)
     add 461ba07  a hot fix for mkldnn link (#11939)
     add 7ffb252  re-enabling randomized test_l2_normalization (#11900)
     add a56a569  [MXNET-651] MXNet Model Backwards Compatibility Checker (#11626)
     add 98a41af  [MXNET-531] NeuralStyle Example for Scala (#11621)
     add ed20304  [MXNET-750] fix nested call on CachedOp. (#11951)
     add 51f650e  extend reshape op to allow reverse shape inference (#11956)
     add 1eef070  Improve sparse embedding index out of bound error message; (#11940)
     add fc912f3  [MXNET-770] Remove fixed seed in flaky test (#11958)
     add 394e5cc  Update ONNX docs with the latest supported ONNX version (#11936)
     add eed7a34  Reduced test to 3 epochs and made gpu only (#11863)
     add c6a32b6  Fix flaky tests for test_laop_4 (#11972)
     add 061076d  Updating R client docs (#11954)
     add 31c5fbc  Fix install instructions for MXNET-R (#11976)
     add a93905d  [MXNET-751] fix ce_loss flaky (#11971)
     add 564e01a  [MXNET-769] set MXNET_HOME as base for downloaded models through base.data_dir() (#11636)
     add 6009b26  [MXNET-748] linker fixed on Scala issues (#11989)
     add 946e9d0  [MXNET-772] Re-enable test_module.py:test_module_set_params (#11979)
     add 1bd9356  [MXNET-771] Fix Flaky Test test_executor.py:test_dot (#11978)
     add 833de7e  remove mod from arity 2 version of load-checkpoint in clojure-package (#11808)
     add bcfab3a  Add unit test stage for mxnet cpu in debug mode (#11974)
     add c937277  Website broken link fixes (#12014)
     add 1818280  removed seed from flaky test (#11975)
     add 619700a  Disable ccache log print due to threadunsafety (#11997)
     add 2534164  Added default tolerance levels for regression checks for MBCC (#12006)
     add 32c2e15  Disable flaky mkldnn test_requantize_int32_to_int8 (#11748)
     add 1fa04f2  [MXNET-769] Usability improvements to windows builds (#11947)
     add 5628194  Fix import statement (#12005)
     add 3dd0003  Disable flaky test test_random.test_gamma_generator (#12022)
     add 3910c08  [MXNET-770] Fix flaky test: test_factorization_machine_module (#12023)
     add ae698f9  disable opencv threading for forked process (#12025)
     add 22c97ef  Bug fixes in control flow operators (#11942)
     add 8d4d5fa  Fix data narrowing warning on graph_executor.cc (#11969)
     new 20246bf  Graph partitioner and subgraph op (#11251)
     new 6393058  Fix duplicate entry bugs (#11767)
     new dbf781c  Make subgraph var node name unique (#11876)
     new 6acf6cc  [DO NOT REVIEW] Fix bug of eliminating cycles (#11907)

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (9c837b0)
            \
             N -- N -- N   refs/heads/subgraph (6acf6cc)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .codecov.yml                                       |   28 +
 .gitignore                                         |    2 +-
 3rdparty/dmlc-core                                 |    2 +-
 3rdparty/mshadow                                   |    2 +-
 3rdparty/tvm                                       |    2 +-
 CMakeLists.txt                                     |    4 +-
 CODEOWNERS                                         |   18 +-
 CONTRIBUTORS.md                                    |    4 +
 Jenkinsfile                                        |  399 ++--
 LICENSE                                            |   52 +-
 MKLDNN_README.md                                   |  301 +++
 MKL_README.md                                      |   77 -
 Makefile                                           |   62 +-
 R-package/R/mlp.R                                  |    2 +-
 R-package/R/model.R                                |    2 +-
 R-package/R/model.rnn.R                            |  170 +-
 R-package/R/optimizer.R                            |  450 +++--
 R-package/tests/testthat/test_optimizer.R          |  204 +++
 README.md                                          |    2 +-
 benchmark/python/control_flow/rnn.py               |  142 ++
 benchmark/python/sparse/sparse_op.py               |    5 +-
 benchmark/python/sparse/util.py                    |    2 +-
 ci/Jenkinsfile_docker_cache                        |    6 +-
 ci/README.md                                       |   11 +-
 ci/build.py                                        |  136 +-
 ci/build_windows.py                                |  253 +++
 ci/docker/Dockerfile.build.android_arm64           |   71 -
 ci/docker/Dockerfile.build.android_armv7           |   53 +-
 ci/docker/Dockerfile.build.android_armv8           |   79 +
 ci/docker/Dockerfile.build.arm64                   |   44 -
 ci/docker/Dockerfile.build.armv8                   |   48 +
 ci/docker/Dockerfile.build.jetson                  |   23 +-
 ci/docker/Dockerfile.build.ubuntu_base_cpu         |   39 +
 ci/docker/Dockerfile.build.ubuntu_base_gpu         |   39 +
 ci/docker/Dockerfile.build.ubuntu_blc              |   40 +
 ci/docker/Dockerfile.build.ubuntu_build_cuda       |    3 +
 ci/docker/Dockerfile.build.ubuntu_cpu              |   16 +
 ci/docker/Dockerfile.build.ubuntu_gpu              |   18 +-
 ci/docker/Dockerfile.build.ubuntu_nightly_cpu      |   75 +
 ci/docker/Dockerfile.build.ubuntu_nightly_gpu      |   80 +
 ci/docker/Dockerfile.build.ubuntu_rat              |   36 +
 ci/docker/install/android_arm64_ndk.sh             |   36 -
 ci/docker/install/android_arm64_openblas.sh        |    2 +-
 ci/docker/install/android_armv7_openblas.sh        |   31 +
 ci/docker/install/android_ndk.sh                   |   38 +
 ci/docker/install/arm64_openblas.sh                |    4 +-
 ci/docker/install/centos7_adduser.sh               |    2 +-
 ci/docker/install/centos7_ccache.sh                |    2 +-
 ci/docker/install/centos7_core.sh                  |    2 +-
 ci/docker/install/centos7_python.sh                |    2 +-
 ci/docker/install/deb_ubuntu_ccache.sh             |    4 +-
 ci/docker/install/export_gpg_keys.sh               |   23 +
 ci/docker/install/r.gpg                            |  Bin 0 -> 1519 bytes
 ci/docker/install/sbt.gpg                          |  Bin 0 -> 2210 bytes
 ci/docker/install/ubuntu_adduser.sh                |   14 +-
 ci/docker/install/ubuntu_arm.sh                    |    2 +-
 ci/docker/install/ubuntu_clang.sh                  |    4 +-
 ci/docker/install/ubuntu_clojure.sh                |   29 +
 ci/docker/install/ubuntu_core.sh                   |    2 +-
 ci/docker/install/ubuntu_docs.sh                   |    2 +-
 ci/docker/install/ubuntu_emscripten.sh             |   40 +
 ci/docker/install/ubuntu_mklml.sh                  |    2 +-
 ci/docker/install/ubuntu_nightly_tests.sh          |   32 +
 ci/docker/install/ubuntu_npm_blc.sh                |   37 +
 ci/docker/install/ubuntu_nvidia.sh                 |    7 +-
 ci/docker/install/ubuntu_perl.sh                   |    2 +-
 ci/docker/install/ubuntu_python.sh                 |    6 +-
 ci/docker/install/ubuntu_r.sh                      |   22 +-
 ci/docker/install/ubuntu_rat.sh                    |   33 +
 ci/docker/install/ubuntu_runas_sudo.sh             |   25 +
 ci/docker/install/ubuntu_scala.sh                  |    8 +-
 ci/docker/install/ubuntu_tutorials.sh              |    2 +-
 ci/docker/install/ubuntu_tvm.sh                    |    2 +-
 ci/docker/runtime_functions.sh                     |  364 ++--
 ci/docker_cache.py                                 |    5 +-
 ci/docker_cache_requirements                       |   16 +
 ci/test_docker_cache.py                            |    4 +-
 ci/util.py                                         |   43 +
 ci/windows/test_py2_cpu.ps1                        |   25 +
 ci/windows/test_py2_gpu.ps1                        |   29 +
 ci/windows/test_py3_cpu.ps1                        |   25 +
 ci/windows/test_py3_gpu.ps1                        |   29 +
 cmake/FirstClassLangCuda.cmake                     |    1 +
 contrib/clojure-package/.gitignore                 |   44 +
 {scala-package => contrib/clojure-package}/LICENSE |    0
 contrib/clojure-package/README.md                  |  236 +++
 contrib/clojure-package/ci-test.sh                 |   23 +
 .../examples/cnn-text-classification/.gitignore    |   11 +
 .../examples/cnn-text-classification/README.md     |   33 +
 .../examples/cnn-text-classification/get_data.sh   |   31 +
 .../examples/cnn-text-classification/project.clj   |   24 +
 .../src/cnn_text_classification/classifier.clj     |  112 ++
 .../src/cnn_text_classification/data_helper.clj    |  144 ++
 contrib/clojure-package/examples/gan/.gitignore    |   11 +
 contrib/clojure-package/examples/gan/README.md     |   16 +
 contrib/clojure-package/examples/gan/project.clj   |   24 +
 .../examples/gan/src/gan/gan_mnist.clj             |  217 +++
 .../clojure-package/examples/gan/src/gan/viz.clj   |   87 +
 .../examples/imclassification/.gitignore           |   11 +
 .../examples/imclassification/README.md            |   18 +
 .../examples/imclassification/project.clj          |   24 +
 .../src/imclassification/train_mnist.clj           |  114 ++
 contrib/clojure-package/examples/module/README.md  |   21 +
 .../clojure-package/examples/module/project.clj    |   25 +
 .../examples/module/src/mnist_mlp.clj              |  237 +++
 .../examples/multi-label/.gitignore                |   11 +
 .../clojure-package/examples/multi-label/README.md |   18 +
 .../examples/multi-label/project.clj               |   23 +
 .../examples/multi-label/src/multi_label/core.clj  |  167 ++
 .../examples/neural-style/.gitignore               |   13 +
 .../examples/neural-style/README.md                |   24 +
 .../examples/neural-style/download.sh              |   33 +
 .../examples/neural-style/project.clj              |   25 +
 .../neural-style/src/neural_style/core.clj         |  254 +++
 .../neural-style/src/neural_style/model_vgg_19.clj |   98 +
 .../examples/pre-trained-models/.gitignore         |   11 +
 .../examples/pre-trained-models/README.md          |   34 +
 .../pre-trained-models/download-caltech.sh         |   26 +
 .../pre-trained-models/download-resnet-152.sh      |   28 +
 .../pre-trained-models/download-resnet-50.sh       |   27 +
 .../examples/pre-trained-models/project.clj        |   25 +
 .../src/pre_trained_models/fine_tune.clj           |  127 ++
 .../src/pre_trained_models/predict_image.clj       |  113 ++
 .../clojure-package/examples/profiler/.gitignore   |   11 +
 .../clojure-package/examples/profiler/README.md    |    6 +
 .../clojure-package/examples/profiler/project.clj  |   22 +
 .../examples/profiler/src/profiler/core.clj        |   59 +
 contrib/clojure-package/examples/rnn/.gitignore    |   11 +
 contrib/clojure-package/examples/rnn/README.md     |   20 +
 contrib/clojure-package/examples/rnn/get_data.sh   |   26 +
 contrib/clojure-package/examples/rnn/project.clj   |   23 +
 .../clojure-package/examples/rnn/src/rnn/lstm.clj  |  192 ++
 .../examples/rnn/src/rnn/test_char_rnn.clj         |   78 +
 .../examples/rnn/src/rnn/train_char_rnn.clj        |  177 ++
 .../clojure-package/examples/rnn/src/rnn/util.clj  |   74 +
 .../examples/scripts/get_cifar_data.sh             |   38 +
 .../examples/scripts/get_mnist_data.sh             |   38 +
 .../clojure-package/examples/tutorial/.gitignore   |   11 +
 .../clojure-package/examples/tutorial/README.md    |    5 +
 .../clojure-package/examples/tutorial/project.clj  |   22 +
 .../tutorial/src/tutorial/introduction.clj         |   34 +
 .../examples/tutorial/src/tutorial/kvstore.clj     |   74 +
 .../examples/tutorial/src/tutorial/module.clj      |  197 ++
 .../examples/tutorial/src/tutorial/ndarray.clj     |   92 +
 .../examples/tutorial/src/tutorial/symbol.clj      |  152 ++
 .../examples/visualization/.gitignore              |   11 +
 .../examples/visualization/README.md               |    4 +
 .../examples/visualization/project.clj             |   23 +
 .../visualization/src/visualization/core.clj       |   46 +
 contrib/clojure-package/lein-cljfmt-check          |   24 +
 contrib/clojure-package/lein-cljfmt-fix            |   24 +
 contrib/clojure-package/project.clj                |   55 +
 contrib/clojure-package/resources/log4j.properties |   22 +
 contrib/clojure-package/scripts/get_cifar_data.sh  |   38 +
 contrib/clojure-package/scripts/get_mnist_data.sh  |   38 +
 contrib/clojure-package/src/dev/generator.clj      |  330 ++++
 .../src/org/apache/clojure_mxnet/base.clj          |   21 +
 .../src/org/apache/clojure_mxnet/callback.clj      |   31 +
 .../src/org/apache/clojure_mxnet/context.clj       |   42 +
 .../src/org/apache/clojure_mxnet/dtype.clj         |   26 +
 .../src/org/apache/clojure_mxnet/eval_metric.clj   |  100 +
 .../src/org/apache/clojure_mxnet/executor.clj      |  101 +
 .../src/org/apache/clojure_mxnet/gen/.gitignore    |    5 +
 .../src/org/apache/clojure_mxnet/initializer.clj   |   57 +
 .../src/org/apache/clojure_mxnet/io.clj            |  313 ++++
 .../src/org/apache/clojure_mxnet/kvstore.clj       |  203 ++
 .../org/apache/clojure_mxnet/kvstore_server.clj    |   37 +
 .../src/org/apache/clojure_mxnet/lr_scheduler.clj  |   27 +
 .../src/org/apache/clojure_mxnet/module.clj        |  671 +++++++
 .../src/org/apache/clojure_mxnet/monitor.clj       |   42 +
 .../src/org/apache/clojure_mxnet/ndarray.clj       |  168 ++
 .../src/org/apache/clojure_mxnet/optimizer.clj     |  177 ++
 .../src/org/apache/clojure_mxnet/profiler.clj      |   47 +
 .../src/org/apache/clojure_mxnet/random.clj        |   61 +
 .../src/org/apache/clojure_mxnet/shape.clj         |   34 +
 .../src/org/apache/clojure_mxnet/symbol.clj        |  237 +++
 .../src/org/apache/clojure_mxnet/util.clj          |  206 +++
 .../src/org/apache/clojure_mxnet/visualization.clj |   60 +
 .../clojure-package/test/dev/generator_test.clj    |  209 +++
 contrib/clojure-package/test/good-test-ndarray.clj |   36 +
 contrib/clojure-package/test/good-test-symbol.clj  |   38 +
 .../org/apache/clojure_mxnet/callback_test.clj     |   34 +
 .../test/org/apache/clojure_mxnet/conv_test.clj    |   88 +
 .../org/apache/clojure_mxnet/eval_metric_test.clj  |   59 +
 .../org/apache/clojure_mxnet/executor_test.clj     |   76 +
 .../test/org/apache/clojure_mxnet/io_test.clj      |  165 ++
 .../test/org/apache/clojure_mxnet/kvstore_test.clj |   81 +
 .../test/org/apache/clojure_mxnet/module_test.clj  |  330 ++++
 .../test/org/apache/clojure_mxnet/ndarray_test.clj |  475 +++++
 .../org/apache/clojure_mxnet/operator_test.clj     |  602 ++++++
 .../org/apache/clojure_mxnet/optimizer_test.clj    |   46 +
 .../test/org/apache/clojure_mxnet/random_test.clj  |   54 +
 .../test/org/apache/clojure_mxnet/shape_test.clj   |   28 +
 .../test/org/apache/clojure_mxnet/symbol_test.clj  |   63 +
 .../test/org/apache/clojure_mxnet/test_util.clj    |   27 +
 .../test/org/apache/clojure_mxnet/util_test.clj    |  185 ++
 contrib/clojure-package/testing.md                 |   23 +
 cpp-package/scripts/OpWrapperGenerator.py          |    1 +
 cpp-package/scripts/lint.py                        |    3 +-
 docs/Jenkinsfile                                   |    6 +-
 docs/README.md                                     |   32 +-
 docs/_static/js/navbar.js                          |    4 +-
 docs/_static/js/options.js                         |   26 +-
 docs/_static/mxnet-theme/index.html                |    6 +-
 docs/_static/mxnet-theme/navbar.html               |    8 +-
 docs/api/clojure/index.md                          |   33 +
 docs/api/clojure/kvstore.md                        |   86 +
 docs/api/clojure/module.md                         |  235 +++
 docs/api/clojure/ndarray.md                        |  118 ++
 docs/api/clojure/symbol.md                         |  150 ++
 docs/api/clojure/symbol_in_pictures.md             |   77 +
 docs/api/python/autograd/autograd.md               |    6 +-
 docs/api/python/callback/callback.md               |    2 +-
 docs/api/python/contrib/onnx.md                    |   20 +-
 docs/api/python/contrib/text.md                    |    2 +-
 docs/api/python/executor/executor.md               |    2 +-
 docs/api/python/gluon/contrib.md                   |    1 +
 docs/api/python/gluon/gluon.md                     |    4 +-
 docs/api/python/gluon/loss.md                      |    2 +-
 docs/api/python/gluon/model_zoo.md                 |   28 +-
 docs/api/python/gluon/nn.md                        |    2 +-
 docs/api/python/gluon/rnn.md                       |    2 +-
 docs/api/python/image/image.md                     |    2 +-
 docs/api/python/io/io.md                           |    2 +-
 docs/api/python/kvstore/kvstore.md                 |    2 +-
 docs/api/python/metric/metric.md                   |    2 +-
 docs/api/python/model.md                           |    2 +-
 docs/api/python/module/module.md                   |    2 +-
 docs/api/python/ndarray/contrib.md                 |    3 +
 docs/api/python/ndarray/ndarray.md                 |   12 +
 docs/api/python/ndarray/sparse.md                  |   67 +-
 docs/api/python/optimization/optimization.md       |    2 +-
 docs/api/python/profiler/profiler.md               |    2 +-
 docs/api/python/rtc/rtc.md                         |    2 +-
 docs/api/python/symbol/contrib.md                  |    3 +
 docs/api/python/symbol/rnn.md                      |    2 +-
 docs/api/python/symbol/symbol.md                   |   12 +
 docs/build_version_doc/README.md                   |  180 +-
 docs/build_version_doc/build_all_version.sh        |   48 +-
 docs/build_version_doc/requirements.txt            |   15 +
 docs/build_version_doc/setup_docs_ubuntu.sh        |  134 +-
 docs/build_version_doc/update_all_version.sh       |    6 +-
 docs/community/contribute.md                       |   14 +-
 docs/community/ecosystem.md                        |   71 +
 docs/community/mxnet_channels.md                   |    8 +-
 docs/faq/bucketing.md                              |    4 +-
 docs/faq/distributed_training.md                   |   21 +-
 docs/faq/env_var.md                                |   30 +
 docs/faq/float16.md                                |  174 ++
 docs/faq/index.md                                  |    1 +
 docs/index.md                                      |    3 +-
 docs/install/build_from_source.md                  |    1 -
 docs/install/download.md                           |    1 +
 docs/install/index.md                              |  268 ++-
 docs/install/install_mxnet_ubuntu_python.sh        |   74 +
 docs/install/install_mxnet_ubuntu_r.sh             |   55 +
 docs/install/osx_setup.md                          |   28 +-
 docs/install/requirements.txt                      |    8 +
 docs/install/scala_setup.md                        |  109 ++
 docs/install/ubuntu_setup.md                       |  322 ++--
 docs/install/windows_setup.md                      |  229 ++-
 docs/model_zoo/index.md                            |    1 +
 docs/mxdoc.py                                      |   14 +
 docs/tutorials/gluon/learning_rate_finder.md       |  325 ++++
 docs/tutorials/gluon/learning_rate_schedules.md    |  328 ++++
 .../gluon/learning_rate_schedules_advanced.md      |  308 ++++
 .../gluon/logistic_regression_explained.md         |  238 +++
 docs/tutorials/gluon/mnist.md                      |   12 +-
 docs/tutorials/gluon/save_load_params.md           |   12 +-
 docs/tutorials/index.md                            |   12 +-
 docs/tutorials/python/predict_image.md             |    4 +-
 docs/tutorials/python/profiler.md                  |   12 +-
 docs/tutorials/scala/README.md                     |    7 -
 docs/tutorials/scala/index.md                      |   17 +
 docs/tutorials/scala/mxnet_scala_on_intellij.md    |  350 ++--
 docs/tutorials/sparse/row_sparse.md                |   11 +-
 docs/tutorials/sparse/train.md                     |    8 +-
 example/README.md                                  |   11 +-
 example/gluon/data.py                              |   36 +
 example/gluon/image_classification.py              |   69 +-
 example/gluon/lstm_crf.py                          |   17 +-
 example/image-classification/benchmark_score.py    |   28 +-
 example/image-classification/common/data.py        |   31 +-
 example/image-classification/common/fit.py         |    2 +-
 example/image-classification/fine-tune.py          |   51 +-
 example/image-classification/train_cifar10.py      |    8 +-
 example/image-classification/train_imagenet.py     |   12 +-
 example/kaggle-ndsb1/gen_img_list.py               |    5 +-
 example/kaggle-ndsb1/train_dsb.py                  |    3 +-
 example/model-parallel/lstm/README.md              |   13 -
 example/model-parallel/lstm/get_ptb_data.sh        |   43 -
 example/model-parallel/lstm/lstm.py                |  532 ------
 example/model-parallel/lstm/lstm_ptb.py            |  128 --
 example/named_entity_recognition/README.md         |   19 +
 example/named_entity_recognition/src/iterators.py  |  175 ++
 example/named_entity_recognition/src/metrics.py    |   79 +
 example/named_entity_recognition/src/ner.py        |  236 +++
 example/named_entity_recognition/src/preprocess.py |   50 +
 example/python-howto/multiple_outputs.py           |    3 +-
 example/rcnn/.gitignore                            |   82 -
 example/rcnn/Makefile                              |    6 -
 example/rcnn/README.md                             |  222 +--
 example/rcnn/demo.py                               |  313 ++--
 example/rcnn/rcnn/__init__.py                      |    0
 example/rcnn/rcnn/config.py                        |  181 --
 example/rcnn/rcnn/core/__init__.py                 |    0
 example/rcnn/rcnn/core/callback.py                 |   28 -
 example/rcnn/rcnn/core/loader.py                   |  414 -----
 example/rcnn/rcnn/core/metric.py                   |  172 --
 example/rcnn/rcnn/core/module.py                   |  232 ---
 example/rcnn/rcnn/core/tester.py                   |  282 ---
 example/rcnn/rcnn/cython/.gitignore                |    3 -
 example/rcnn/rcnn/cython/__init__.py               |    0
 example/rcnn/rcnn/cython/bbox.pyx                  |   55 -
 example/rcnn/rcnn/cython/cpu_nms.pyx               |   68 -
 example/rcnn/rcnn/cython/gpu_nms.hpp               |   21 -
 example/rcnn/rcnn/cython/gpu_nms.pyx               |   31 -
 example/rcnn/rcnn/cython/nms_kernel.cu             |  144 --
 example/rcnn/rcnn/cython/setup.py                  |  163 --
 example/rcnn/rcnn/dataset/__init__.py              |   20 -
 example/rcnn/rcnn/dataset/coco.py                  |  249 ---
 example/rcnn/rcnn/dataset/ds_utils.py              |   33 -
 example/rcnn/rcnn/dataset/imdb.py                  |  314 ----
 example/rcnn/rcnn/dataset/pascal_voc.py            |  280 ---
 example/rcnn/rcnn/dataset/pascal_voc_eval.py       |  194 --
 example/rcnn/rcnn/io/__init__.py                   |    0
 example/rcnn/rcnn/io/image.py                      |  157 --
 example/rcnn/rcnn/io/rcnn.py                       |  194 --
 example/rcnn/rcnn/io/rpn.py                        |  244 ---
 example/rcnn/rcnn/processing/bbox_regression.py    |  137 --
 example/rcnn/rcnn/processing/bbox_transform.py     |  179 --
 example/rcnn/rcnn/processing/generate_anchor.py    |   89 -
 example/rcnn/rcnn/processing/nms.py                |   81 -
 example/rcnn/rcnn/pycocotools/UPSTREAM_REV         |    1 -
 example/rcnn/rcnn/pycocotools/__init__.py          |   18 -
 example/rcnn/rcnn/pycocotools/_mask.pyx            |  308 ----
 example/rcnn/rcnn/pycocotools/coco.py              |  445 -----
 example/rcnn/rcnn/pycocotools/cocoeval.py          |  545 ------
 example/rcnn/rcnn/pycocotools/mask.py              |  120 --
 example/rcnn/rcnn/pycocotools/maskApi.c            |  249 ---
 example/rcnn/rcnn/pycocotools/maskApi.h            |   79 -
 example/rcnn/rcnn/pycocotools/setup.py             |   37 -
 example/rcnn/rcnn/symbol/__init__.py               |   19 -
 example/rcnn/rcnn/symbol/proposal.py               |  241 ---
 example/rcnn/rcnn/symbol/proposal_target.py        |  113 --
 example/rcnn/rcnn/symbol/symbol_resnet.py          |  229 ---
 example/rcnn/rcnn/symbol/symbol_vgg.py             |  424 -----
 example/rcnn/rcnn/tools/reeval.py                  |   67 -
 example/rcnn/rcnn/tools/test_rcnn.py               |  126 --
 example/rcnn/rcnn/tools/test_rpn.py                |  116 --
 example/rcnn/rcnn/tools/train_rcnn.py              |  189 --
 example/rcnn/rcnn/tools/train_rpn.py               |  189 --
 example/rcnn/rcnn/utils/combine_model.py           |   39 -
 example/rcnn/rcnn/utils/load_data.py               |   69 -
 example/rcnn/rcnn/utils/load_model.py              |   76 -
 example/rcnn/rcnn/utils/save_model.py              |   35 -
 example/rcnn/script/additional_deps.sh             |   26 -
 example/rcnn/script/get_coco.sh                    |   58 -
 example/rcnn/script/get_pretrained_model.sh        |   31 -
 example/rcnn/script/get_selective_search.sh        |   33 -
 example/rcnn/script/get_voc.sh                     |   50 -
 example/rcnn/script/resnet_voc07.sh                |   30 -
 example/rcnn/script/resnet_voc0712.sh              |   30 -
 example/rcnn/script/vgg_alter_voc07.sh             |   30 -
 example/rcnn/script/vgg_fast_rcnn.sh               |   30 -
 example/rcnn/script/vgg_voc07.sh                   |   30 -
 example/rcnn/script/vgg_voc0712.sh                 |   30 -
 example/rcnn/{rcnn/utils => symdata}/__init__.py   |    0
 example/rcnn/symdata/anchor.py                     |  176 ++
 example/rcnn/symdata/bbox.py                       |  214 +++
 example/rcnn/symdata/image.py                      |  144 ++
 example/rcnn/symdata/loader.py                     |  243 +++
 example/rcnn/symdata/vis.py                        |   32 +
 example/rcnn/{rcnn/tools => symimdb}/__init__.py   |    0
 example/rcnn/symimdb/coco.py                       |  210 +++
 example/rcnn/symimdb/imdb.py                       |  126 ++
 example/rcnn/symimdb/pascal_voc.py                 |  269 +++
 .../rcnn/{rcnn/processing => symnet}/__init__.py   |    0
 example/rcnn/{rcnn => symnet}/logger.py            |    0
 example/rcnn/symnet/metric.py                      |  147 ++
 example/rcnn/symnet/model.py                       |   88 +
 example/rcnn/symnet/proposal_target.py             |  175 ++
 example/rcnn/symnet/symbol_resnet.py               |  225 +++
 example/rcnn/symnet/symbol_vgg.py                  |  232 +++
 example/rcnn/test.py                               |  222 ++-
 example/rcnn/train.py                              |  303 +++
 example/rcnn/train_alternate.py                    |  121 --
 example/rcnn/train_end2end.py                      |  195 --
 example/reinforcement-learning/ddpg/ddpg.py        |    4 +-
 example/reinforcement-learning/ddpg/strategies.py  |    4 +-
 example/rnn-time-major/get_ptb_data.sh             |   43 -
 example/rnn-time-major/get_sherlockholmes_data.sh  |   43 +
 example/rnn-time-major/readme.md                   |   12 +-
 example/rnn-time-major/rnn_cell_demo.py            |    8 +-
 example/rnn/README.md                              |    2 +-
 example/rnn/bucketing/README.md                    |   10 +-
 example/rnn/bucketing/cudnn_rnn_bucketing.py       |   22 +-
 example/rnn/bucketing/get_ptb_data.sh              |   43 -
 example/rnn/bucketing/get_sherlockholmes_data.sh   |   43 +
 example/rnn/bucketing/lstm_bucketing.py            |   10 +-
 example/rnn/large_word_lm/LogUniformGenerator.cc   |   52 +
 example/rnn/large_word_lm/LogUniformGenerator.h    |   45 +
 example/rnn/large_word_lm/Makefile                 |   25 +
 example/rnn/large_word_lm/custom_module.py         |    3 +-
 example/rnn/large_word_lm/log_uniform.pyx          |   38 +
 example/rnn/large_word_lm/model.py                 |   21 +-
 example/rnn/large_word_lm/readme.md                |   16 +-
 example/rnn/large_word_lm/run_utils.py             |   11 +-
 example/rnn/large_word_lm/sampler.py               |   55 +
 example/rnn/large_word_lm/setup.py                 |   28 +
 example/rnn/large_word_lm/train.py                 |   32 +-
 example/rnn/old/README.md                          |    6 +-
 example/rnn/old/bucket_io.py                       |    2 +-
 example/rnn/old/get_ptb_data.sh                    |   43 -
 example/rnn/old/get_sherlockholmes_data.sh         |   43 +
 example/rnn/old/gru_bucketing.py                   |    8 +-
 example/rnn/old/lstm_bucketing.py                  |    8 +-
 example/rnn/old/lstm_ptb.R                         |  123 --
 example/rnn/old/lstm_sherlockholmes.R              |  123 ++
 example/rnn/old/rnn_cell_demo.py                   |    8 +-
 example/rnn/word_lm/README.md                      |    6 +-
 example/rnn/word_lm/get_ptb_data.sh                |   43 -
 example/rnn/word_lm/get_sherlockholmes_data.sh     |   43 +
 example/rnn/word_lm/train.py                       |    4 +-
 example/sparse/factorization_machine/metric.py     |   37 +-
 example/sparse/factorization_machine/train.py      |   29 +-
 example/sparse/linear_classification/train.py      |    7 +-
 example/speech_recognition/singleton.py            |    3 +-
 example/ssd/benchmark_score.py                     |    2 +-
 example/ssd/dataset/pycocotools/coco.py            |   12 +-
 .../ssd/tools/caffe_converter/compare_layers.py    |    3 +-
 include/mxnet/c_api.h                              |   54 +
 include/mxnet/engine.h                             |    4 +-
 include/mxnet/kvstore.h                            |    6 +-
 include/mxnet/ndarray.h                            |   11 +-
 include/mxnet/op_attr_types.h                      |    8 +-
 mkldnn.mk                                          |   56 +
 perl-package/AI-MXNet-Gluon-Contrib/Changes        |    5 +
 perl-package/AI-MXNet-Gluon-Contrib/MANIFEST       |    9 +
 perl-package/AI-MXNet-Gluon-Contrib/META.json      |   42 +
 perl-package/AI-MXNet-Gluon-Contrib/META.yml       |   21 +
 perl-package/AI-MXNet-Gluon-Contrib/Makefile.PL    |   63 +
 perl-package/AI-MXNet-Gluon-Contrib/README         |    7 +
 .../lib/AI/MXNet/Gluon/Contrib.pm                  |   24 +
 .../lib/AI/MXNet/Gluon/Contrib/NN/BasicLayers.pm   |  201 ++
 .../t/AI-MXNet-Gluon-Contrib.t                     |   21 +
 perl-package/AI-MXNet-Gluon-ModelZoo/Changes       |    5 +
 perl-package/AI-MXNet-Gluon-ModelZoo/MANIFEST      |   19 +
 perl-package/AI-MXNet-Gluon-ModelZoo/META.json     |   43 +
 perl-package/AI-MXNet-Gluon-ModelZoo/META.yml      |   22 +
 perl-package/AI-MXNet-Gluon-ModelZoo/Makefile.PL   |   65 +
 perl-package/AI-MXNet-Gluon-ModelZoo/README        |    7 +
 .../examples/image_classification.pl               |   77 +
 .../lib/AI/MXNet/Gluon/ModelZoo.pm                 |  132 ++
 .../lib/AI/MXNet/Gluon/ModelZoo/ModelStore.pm      |  164 ++
 .../lib/AI/MXNet/Gluon/ModelZoo/Vision.pm          |   48 +
 .../lib/AI/MXNet/Gluon/ModelZoo/Vision/AlexNet.pm  |  115 ++
 .../lib/AI/MXNet/Gluon/ModelZoo/Vision/DenseNet.pm |  277 +++
 .../AI/MXNet/Gluon/ModelZoo/Vision/Inception.pm    |  287 +++
 .../AI/MXNet/Gluon/ModelZoo/Vision/MobileNet.pm    |  518 ++++++
 .../lib/AI/MXNet/Gluon/ModelZoo/Vision/ResNet.pm   |  828 +++++++++
 .../AI/MXNet/Gluon/ModelZoo/Vision/SqueezeNet.pm   |  212 +++
 .../lib/AI/MXNet/Gluon/ModelZoo/Vision/VGG.pm      |  321 ++++
 .../t/AI-MXNet-Gluon-ModelZoo.t                    |   21 +
 .../t/test_gluon_model_zoo.t                       |   51 +
 perl-package/AI-MXNet/Changes                      |   12 +
 perl-package/AI-MXNet/MANIFEST                     |   11 +-
 perl-package/AI-MXNet/META.json                    |    6 +-
 perl-package/AI-MXNet/META.yml                     |    6 +-
 perl-package/AI-MXNet/Makefile.PL                  |   10 +-
 perl-package/AI-MXNet/README                       |    2 +-
 perl-package/AI-MXNet/examples/char_lstm.pl        |   11 +-
 .../AI-MXNet/examples/cudnn_lstm_bucketing.pl      |    4 +-
 perl-package/AI-MXNet/examples/get_ptb_data.sh     |   43 -
 .../AI-MXNet/examples/get_sherlockholmes_data.sh   |   43 +
 perl-package/AI-MXNet/examples/gluon/mnist.pl      |    4 +-
 .../examples/gluon/style_transfer/README.md        |   35 +
 .../examples/gluon/style_transfer/get_data.sh      |   31 +
 .../AI-MXNet/examples/gluon/style_transfer/net.pl  |  325 ++++
 .../gluon/style_transfer/style_transfer.pl         |   58 +
 .../examples/gluon/style_transfer/utils.pl         |   73 +
 perl-package/AI-MXNet/examples/lstm_bucketing.pl   |    6 +-
 perl-package/AI-MXNet/lib/AI/MXNet.pm              |    8 +-
 perl-package/AI-MXNet/lib/AI/MXNet/AutoLoad.pm     |    2 +-
 perl-package/AI-MXNet/lib/AI/MXNet/Base.pm         |   25 +-
 perl-package/AI-MXNet/lib/AI/MXNet/CachedOp.pm     |   22 +-
 perl-package/AI-MXNet/lib/AI/MXNet/Context.pm      |   44 +
 perl-package/AI-MXNet/lib/AI/MXNet/Engine.pm       |   84 +
 perl-package/AI-MXNet/lib/AI/MXNet/Executor.pm     |  160 +-
 .../AI-MXNet/lib/AI/MXNet/Executor/Group.pm        |    2 +-
 perl-package/AI-MXNet/lib/AI/MXNet/Gluon.pm        |    8 +-
 perl-package/AI-MXNet/lib/AI/MXNet/Gluon/Block.pm  |  904 +++++++--
 perl-package/AI-MXNet/lib/AI/MXNet/Gluon/NN.pm     |    1 +
 .../AI-MXNet/lib/AI/MXNet/Gluon/NN/Activation.pm   |  249 +++
 .../AI-MXNet/lib/AI/MXNet/Gluon/NN/BasicLayers.pm  |  485 +++--
 .../AI-MXNet/lib/AI/MXNet/Gluon/NN/ConvLayers.pm   |   55 +-
 .../AI-MXNet/lib/AI/MXNet/Gluon/Parameter.pm       |  557 +++++-
 perl-package/AI-MXNet/lib/AI/MXNet/Gluon/RNN.pm    |    2 +-
 .../AI-MXNet/lib/AI/MXNet/Gluon/RNN/Cell.pm        |   19 +-
 .../AI-MXNet/lib/AI/MXNet/Gluon/Trainer.pm         |  385 +++-
 perl-package/AI-MXNet/lib/AI/MXNet/Gluon/Utils.pm  |   55 +-
 perl-package/AI-MXNet/lib/AI/MXNet/Image.pm        |    6 +-
 perl-package/AI-MXNet/lib/AI/MXNet/Module.pm       |   16 +
 .../AI-MXNet/lib/AI/MXNet/Module/Bucketing.pm      |    4 +-
 perl-package/AI-MXNet/lib/AI/MXNet/NDArray.pm      |   67 +-
 perl-package/AI-MXNet/lib/AI/MXNet/Optimizer.pm    |   12 +-
 perl-package/AI-MXNet/lib/AI/MXNet/Random.pm       |   34 +-
 perl-package/AI-MXNet/lib/AI/MXNet/Symbol.pm       |   12 +
 .../AI-MXNet/lib/AI/MXNet/Visualization.pm         |   30 +-
 perl-package/AI-MXNet/t/test_conv.t                |    2 +-
 perl-package/AI-MXNet/t/test_cuda_module.t         |    2 +-
 perl-package/AI-MXNet/t/test_engine.t              |   41 +
 perl-package/AI-MXNet/t/test_executor.t            |    8 +-
 perl-package/AI-MXNet/t/test_gluon.t               |  909 ++++++++-
 perl-package/AI-MXNet/t/test_gluon_trainer.t       |  253 +++
 perl-package/AI-MXNet/t/test_loss.t                |   28 +-
 perl-package/AI-MXNet/t/test_ndarray.t             |   81 +-
 perl-package/AI-MXNet/t/test_optimizers.t          |    3 +-
 perl-package/AI-MXNet/t/test_random.t              |   12 +-
 perl-package/AI-MXNet/t/test_symbol.t              |   13 +-
 perl-package/AI-MXNetCAPI/Changes                  |    3 +
 perl-package/AI-MXNetCAPI/META.json                |    2 +-
 perl-package/AI-MXNetCAPI/META.yml                 |    2 +-
 perl-package/AI-MXNetCAPI/README                   |    2 +-
 perl-package/AI-MXNetCAPI/lib/AI/MXNetCAPI.pm      |    2 +-
 perl-package/AI-MXNetCAPI/mxnet.i                  |  106 ++
 perl-package/AI-MXNetCAPI/mxnet_typemaps.i         |   75 +-
 perl-package/AI-NNVMCAPI/Changes                   |    3 +
 perl-package/AI-NNVMCAPI/META.json                 |    2 +-
 perl-package/AI-NNVMCAPI/META.yml                  |    2 +-
 perl-package/AI-NNVMCAPI/README                    |    2 +-
 perl-package/AI-NNVMCAPI/lib/AI/NNVMCAPI.pm        |    2 +-
 perl-package/AI-NNVMCAPI/nnvm_typemaps.i           |    5 +
 perl-package/test.sh                               |   10 +
 prepare_mkl.sh                                     |  108 --
 prepare_mkldnn.sh                                  |  135 --
 python/mxnet/base.py                               |   81 +-
 python/mxnet/callback.py                           |    6 +-
 python/mxnet/contrib/onnx/__init__.py              |    5 +-
 python/mxnet/contrib/onnx/_import/import_helper.py |  127 --
 python/mxnet/contrib/onnx/_import/import_onnx.py   |  226 ---
 .../mxnet/contrib/onnx/_import/import_to_gluon.py  |   48 -
 .../mxnet/contrib/onnx/_import/op_translations.py  |  587 ------
 .../contrib/onnx/_import/translation_utils.py      |  242 ---
 python/mxnet/contrib/onnx/mx2onnx/LICENSE          |   44 +
 python/mxnet/contrib/onnx/mx2onnx/__init__.py      |   24 +
 .../mxnet/contrib/onnx/mx2onnx/_export_helper.py   |   65 +
 .../mxnet/contrib/onnx/mx2onnx/_op_translations.py | 1929 ++++++++++++++++++++
 python/mxnet/contrib/onnx/mx2onnx/export_model.py  |   95 +
 python/mxnet/contrib/onnx/mx2onnx/export_onnx.py   |  347 ++++
 .../contrib/onnx/{_import => onnx2mx}/__init__.py  |    0
 .../mxnet/contrib/onnx/onnx2mx/_import_helper.py   |  144 ++
 .../mxnet/contrib/onnx/onnx2mx/_op_translations.py |  674 +++++++
 .../contrib/onnx/onnx2mx/_translation_utils.py     |  243 +++
 .../onnx/{_import => onnx2mx}/import_model.py      |    0
 python/mxnet/contrib/onnx/onnx2mx/import_onnx.py   |  224 +++
 .../mxnet/contrib/onnx/onnx2mx/import_to_gluon.py  |   48 +
 python/mxnet/contrib/quantization.py               |   33 +-
 python/mxnet/contrib/tensorboard.py                |    4 +-
 python/mxnet/contrib/text/embedding.py             |    9 +-
 python/mxnet/contrib/text/utils.py                 |   12 +-
 python/mxnet/gluon/block.py                        |   23 +-
 python/mxnet/gluon/contrib/data/text.py            |   11 +-
 python/mxnet/gluon/contrib/nn/basic_layers.py      |   90 +-
 python/mxnet/gluon/data/dataloader.py              |    1 +
 python/mxnet/gluon/data/dataset.py                 |   13 +-
 python/mxnet/gluon/data/vision/datasets.py         |   18 +-
 python/mxnet/gluon/model_zoo/model_store.py        |   45 +-
 python/mxnet/gluon/model_zoo/vision/__init__.py    |    2 +-
 python/mxnet/gluon/model_zoo/vision/alexnet.py     |    5 +-
 python/mxnet/gluon/model_zoo/vision/densenet.py    |   13 +-
 python/mxnet/gluon/model_zoo/vision/inception.py   |    5 +-
 python/mxnet/gluon/model_zoo/vision/mobilenet.py   |    9 +-
 python/mxnet/gluon/model_zoo/vision/resnet.py      |   25 +-
 python/mxnet/gluon/model_zoo/vision/squeezenet.py  |    9 +-
 python/mxnet/gluon/model_zoo/vision/vgg.py         |   21 +-
 python/mxnet/gluon/nn/basic_layers.py              |    5 +
 python/mxnet/gluon/nn/conv_layers.py               |  122 +-
 python/mxnet/gluon/rnn/rnn_cell.py                 |  106 +-
 python/mxnet/gluon/rnn/rnn_layer.py                |   10 +-
 python/mxnet/gluon/trainer.py                      |   60 +-
 python/mxnet/gluon/utils.py                        |   14 +-
 python/mxnet/image/image.py                        |   25 +-
 python/mxnet/kvstore.py                            |   19 +-
 python/mxnet/metric.py                             |  124 +-
 python/mxnet/module/base_module.py                 |   13 +-
 python/mxnet/ndarray/contrib.py                    |  358 +++-
 python/mxnet/ndarray/ndarray.py                    |  113 +-
 python/mxnet/notebook/callback.py                  |    6 +-
 python/mxnet/optimizer.py                          |    8 +-
 python/mxnet/rnn/io.py                             |    7 +-
 python/mxnet/symbol/contrib.py                     |  610 ++++++-
 python/mxnet/symbol/register.py                    |    8 +
 python/mxnet/symbol/symbol.py                      |   80 +-
 python/mxnet/test_utils.py                         |   18 +-
 python/mxnet/util.py                               |   30 +
 python/mxnet/visualization.py                      |   11 +-
 python/setup.py                                    |   24 +
 scala-package/README.md                            |    5 +-
 scala-package/assembly/linux-x86_64-cpu/pom.xml    |   65 +-
 scala-package/assembly/linux-x86_64-gpu/pom.xml    |   65 +-
 scala-package/assembly/osx-x86_64-cpu/pom.xml      |   70 +
 scala-package/assembly/pom.xml                     |    9 +-
 scala-package/assembly/src/javadoc.xml             |   24 +
 scala-package/assembly/src/source.xml              |   32 +
 scala-package/core/pom.xml                         |   29 +
 scala-package/core/scripts/get_cifar_data.sh       |    4 +-
 scala-package/core/scripts/get_mnist_data.sh       |    4 +-
 .../src/main/scala/org/apache/mxnet/Base.scala     |    2 +-
 .../src/main/scala/org/apache/mxnet/Executor.scala |    2 +-
 .../core/src/main/scala/org/apache/mxnet/IO.scala  |    6 +-
 .../src/main/scala/org/apache/mxnet/Monitor.scala  |    2 +-
 .../src/main/scala/org/apache/mxnet/NDArray.scala  |   22 +-
 .../main/scala/org/apache/mxnet/NDArrayAPI.scala   |    1 +
 .../scala/org/apache/mxnet/NDArrayCollector.scala  |  159 ++
 .../src/main/scala/org/apache/mxnet/Operator.scala |    4 +-
 .../src/main/scala/org/apache/mxnet/RecordIO.scala |    2 +-
 .../src/main/scala/org/apache/mxnet/Symbol.scala   |    6 +-
 .../main/scala/org/apache/mxnet/SymbolAPI.scala    |    8 +
 .../scala/org/apache/mxnet/io/NDArrayIter.scala    |   17 +-
 .../org/apache/mxnet/NDArrayCollectorSuite.scala   |   71 +
 .../test/scala/org/apache/mxnet/NDArraySuite.scala |    5 +-
 .../scala/org/apache/mxnet/OperatorSuite.scala     |    9 +-
 .../src/test/scala/org/apache/mxnet/TestUtil.scala |    2 +-
 scala-package/dev/compile-mxnet-backend.sh         |  108 ++
 scala-package/examples/pom.xml                     |   20 +-
 .../main/scala/org/apache/mxnetexamples/Util.scala |   45 +
 .../CNNTextClassification.scala                    |  328 ++--
 .../cnntextclassification/DataHelper.scala         |   27 +-
 .../mxnetexamples/cnntextclassification/README.md  |   23 +
 .../org/apache/mxnetexamples/customop/Data.scala   |    7 +-
 .../mxnetexamples/customop/ExampleCustomOp.scala   |  230 ++-
 .../customop/ExampleCustomOpWithRtc.scala          |  222 ++-
 .../org/apache/mxnetexamples/customop/README.md    |   22 +
 .../org/apache/mxnetexamples/gan/GanMnist.scala    |  229 ++-
 .../org/apache/mxnetexamples/gan/Module.scala      |    3 -
 .../scala/org/apache/mxnetexamples/gan/README.md   |   18 +
 .../imclassification/ModelTrain.scala              |    6 +-
 .../mxnetexamples/imclassification/README.md       |   17 +
 .../imclassification/TrainMnist.scala              |   22 +-
 .../imageclassifier/ImageClassifierExample.scala   |   12 +-
 .../mxnetexamples/infer/imageclassifier/README.md  |    2 +-
 .../mxnetexamples/infer/objectdetector/README.md   |    2 +-
 .../objectdetector/SSDClassifierExample.scala      |    6 +-
 .../mxnetexamples/multitask/ExampleMultiTask.scala |  259 +--
 .../mxnetexamples/neuralstyle/ModelVgg19.scala     |  139 +-
 .../mxnetexamples/neuralstyle/NeuralStyle.scala    |  251 +--
 .../org/apache/mxnetexamples/neuralstyle/README.md |   83 +
 .../mxnetexamples/neuralstyle/end2end/Basic.scala  |   32 +-
 .../neuralstyle/end2end/BoostInference.scala       |   60 +-
 .../neuralstyle/end2end/BoostTrain.scala           |  271 ++-
 .../neuralstyle/end2end/DataProcessing.scala       |   15 +-
 .../mxnetexamples/neuralstyle/end2end/GenV3.scala  |   55 +-
 .../mxnetexamples/neuralstyle/end2end/GenV4.scala  |   91 +-
 .../neuralstyle/end2end/ModelVgg19.scala           |  111 --
 .../mxnetexamples/neuralstyle/end2end/Module.scala |   15 +-
 .../mxnetexamples/profiler/ProfilerMatMul.scala    |    2 +-
 .../mxnetexamples/profiler/ProfilerNDArray.scala   |   10 +-
 .../apache/mxnetexamples/rnn/LstmBucketing.scala   |    4 +-
 .../CNNClassifierExampleSuite.scala                |   70 +
 .../customop/CustomOpExampleSuite.scala            |   84 +
 .../apache/mxnetexamples/gan/GanExampleSuite.scala |   55 +
 .../imclassification/MNISTExampleSuite.scala       |   57 +
 .../ImageClassifierExampleSuite.scala              |   34 +-
 .../ObjectDetectorExampleSuite.scala               |   37 +-
 .../mxnetexamples/multitask/MultiTaskSuite.scala   |   67 +
 .../neuralstyle/NeuralStyleSuite.scala             |   92 +
 .../mxnetexamples/profiler/ProfilerSuite.scala     |   79 +
 scala-package/infer/pom.xml                        |   20 +
 scala-package/init-native/linux-x86_64/pom.xml     |    9 +-
 scala-package/init-native/osx-x86_64/pom.xml       |   11 +-
 scala-package/init-native/pom.xml                  |   13 +
 scala-package/init/pom.xml                         |   33 +
 scala-package/macros/pom.xml                       |   25 +
 .../scala/org/apache/mxnet/APIDocGenerator.scala   |   78 +-
 .../main/scala/org/apache/mxnet/NDArrayMacro.scala |    9 +-
 .../main/scala/org/apache/mxnet/SymbolMacro.scala  |    8 +-
 .../org/apache/mxnet/utils/CToScalaUtils.scala     |   15 +-
 .../test/scala/org/apache/mxnet/MacrosSuite.scala  |    2 +-
 scala-package/mxnet-demo/Makefile                  |   54 +
 scala-package/mxnet-demo/README.md                 |   67 +
 scala-package/mxnet-demo/bin/demo.sh               |   20 +
 scala-package/mxnet-demo/bin/run_im.sh             |   21 +
 scala-package/mxnet-demo/pom.xml                   |  103 ++
 .../src/main/scala/sample/HelloWorld.scala         |   26 +
 .../scala/sample/ImageClassificationExample.scala  |   97 +
 scala-package/native/linux-x86_64-cpu/pom.xml      |    9 +-
 scala-package/native/linux-x86_64-gpu/pom.xml      |    9 +-
 scala-package/native/osx-x86_64-cpu/pom.xml        |   11 +-
 scala-package/native/pom.xml                       |   13 +
 .../main/native/org_apache_mxnet_native_c_api.cc   |    2 +-
 scala-package/pom.xml                              |  107 +-
 scala-package/spark/bin/run-mnist-example.sh       |    4 +-
 .../scala/org/apache/mxnet/spark/MXNDArray.scala   |    2 +-
 .../scala/org/apache/mxnet/spark/MXNetModel.scala  |    4 +-
 .../org/apache/mxnet/spark/MXNetGeneralSuite.scala |    8 +-
 src/c_api/c_api.cc                                 |   49 +-
 src/c_api/c_api_symbolic.cc                        |   71 +
 src/common/cuda_utils.h                            |   30 +
 src/common/exec_utils.h                            |   15 +-
 src/common/utils.h                                 |   42 +
 src/engine/threaded_engine_perdevice.cc            |   57 +-
 src/executor/graph_executor.cc                     |   11 +-
 src/executor/graph_executor.h                      |    2 +
 src/imperative/cached_op.cc                        |  251 ++-
 src/imperative/cached_op.h                         |   27 +-
 src/imperative/imperative.cc                       |    3 +-
 src/imperative/imperative_utils.cc                 |    4 +-
 src/imperative/imperative_utils.h                  |   25 +-
 src/initialize.cc                                  |    6 +
 src/io/image_aug_default.cc                        |    4 +-
 src/io/image_iter_common.h                         |    1 +
 src/io/iter_csv.cc                                 |   16 +-
 src/kvstore/comm.h                                 |  126 +-
 src/kvstore/comm_tree.h                            |  532 ++++++
 src/kvstore/gpu_topology.h                         | 1100 +++++++++++
 src/kvstore/kvstore_dist.h                         |    9 +-
 src/kvstore/kvstore_dist_server.h                  |    2 -
 src/kvstore/kvstore_local.h                        |   72 +-
 src/kvstore/kvstore_nccl.h                         |   16 +-
 src/kvstore/kvstore_utils.cc                       |    4 +-
 src/kvstore/kvstore_utils.cu                       |   19 +-
 src/kvstore/kvstore_utils.h                        |    7 +-
 src/ndarray/ndarray.cc                             |   81 +-
 src/ndarray/ndarray_function.cc                    |  108 +-
 src/ndarray/ndarray_function.cu                    |  108 +-
 src/nnvm/graph_editor.cc                           |  108 ++
 src/operator/batch_norm_v1.cc                      |    3 +
 src/operator/contrib/bilinear_resize-inl.h         |    4 +-
 src/operator/contrib/count_sketch.cu               |    9 +-
 src/operator/contrib/ctc_include/detail/gpu_ctc.h  |    7 +-
 src/operator/contrib/ctc_loss-inl.h                |    4 +-
 src/operator/contrib/deformable_convolution-inl.h  |    2 +-
 src/operator/contrib/multi_proposal.cc             |    2 +-
 src/operator/contrib/proposal.cc                   |    2 +-
 src/operator/contrib/roi_align-inl.h               |    3 +
 src/operator/contrib/roi_align.cc                  |    6 +-
 src/operator/contrib/roi_align.cu                  |   21 +-
 src/operator/contrib/sync_batch_norm-inl.h         |  594 ++++++
 src/operator/contrib/sync_batch_norm.cc            |  117 ++
 src/operator/contrib/sync_batch_norm.cu            |   37 +
 src/operator/control_flow.cc                       | 1440 +++++++++++++++
 src/operator/elemwise_op_common.h                  |   10 +
 src/operator/leaky_relu-inl.h                      |    4 +-
 src/operator/linalg_impl.h                         |   59 +-
 src/operator/mshadow_op.h                          |  132 ++
 src/operator/nn/activation-inl.h                   |    7 +-
 src/operator/nn/activation.cc                      |   29 +-
 src/operator/nn/activation.cu                      |    2 +-
 src/operator/nn/batch_norm.cc                      |   54 +-
 src/operator/nn/concat.cc                          |   20 +-
 src/operator/nn/convolution.cu                     |   32 +-
 src/operator/nn/cudnn/cudnn_algoreg-inl.h          |   11 +-
 src/operator/nn/cudnn/cudnn_convolution-inl.h      |   36 +-
 src/operator/nn/cudnn/cudnn_deconvolution-inl.h    |   38 +-
 src/operator/nn/deconvolution.cu                   |   20 +-
 src/operator/nn/fully_connected-inl.h              |    1 +
 src/operator/nn/fully_connected.cc                 |   23 +-
 src/operator/nn/lrn.cc                             |    2 +-
 src/operator/nn/mkldnn/mkldnn_act.cc               |    6 +-
 src/operator/nn/mkldnn/mkldnn_base-inl.h           |   10 +
 src/operator/nn/mkldnn/mkldnn_base.cc              |  149 +-
 src/operator/nn/mkldnn/mkldnn_concat.cc            |   12 +-
 src/operator/nn/mkldnn/mkldnn_copy.cc              |   15 +-
 src/operator/nn/mkldnn/mkldnn_pooling-inl.h        |   10 +-
 src/operator/nn/mkldnn/mkldnn_pooling.cc           |   23 +-
 src/operator/nn/mkldnn/mkldnn_softmax.cc           |    9 +
 src/operator/nn/mkldnn/mkldnn_sum.cc               |   20 +-
 src/operator/nn/pooling.cc                         |   54 +-
 src/operator/nn/softmax-inl.h                      |   82 +-
 src/operator/nn/softmax.cc                         |    7 +-
 src/operator/operator_common.h                     |    6 +-
 src/operator/operator_tune-inl.h                   |   10 +-
 src/operator/optimizer_op-inl.h                    |   34 +-
 .../mkldnn/mkldnn_quantized_pooling.cc             |    4 +-
 src/operator/random/sampler.h                      |    7 +-
 src/operator/rnn-inl.h                             |   74 +-
 src/operator/rnn_impl.h                            | 1045 ++++++++++-
 src/operator/spatial_transformer.cu                |   15 +-
 src/operator/subgraph_op_common.cc                 |  281 +++
 src/operator/subgraph_op_common.h                  |  173 ++
 src/operator/tensor/broadcast_reduce-inl.cuh       |   47 +-
 src/operator/tensor/broadcast_reduce-inl.h         |   50 +-
 src/operator/tensor/broadcast_reduce_op.h          |  103 +-
 src/operator/tensor/broadcast_reduce_op_value.cc   |   71 +-
 src/operator/tensor/broadcast_reduce_op_value.cu   |    7 +-
 src/operator/tensor/diag_op-inl.h                  |  217 +++
 src/operator/tensor/diag_op.cc                     |   93 +
 src/operator/tensor/diag_op.cu                     |   39 +
 src/operator/tensor/dot-inl.cuh                    |  316 ++--
 src/operator/tensor/dot-inl.h                      |    2 +-
 src/operator/tensor/dot.cc                         |    8 +
 .../tensor/elemwise_binary_broadcast_op-inl.cuh    |   64 +
 src/operator/tensor/elemwise_binary_broadcast_op.h |   38 +-
 src/operator/tensor/elemwise_binary_op-inl.h       |   45 +-
 src/operator/tensor/elemwise_binary_op.h           |   17 +-
 src/operator/tensor/elemwise_binary_op_basic.cu    |   54 +
 src/operator/tensor/elemwise_sum.cc                |   10 +-
 src/operator/tensor/elemwise_sum.cu                |    6 +-
 src/operator/tensor/elemwise_unary_op.h            |    2 +
 src/operator/tensor/elemwise_unary_op_basic.cc     |  159 +-
 src/operator/tensor/elemwise_unary_op_basic.cu     |   46 +
 src/operator/tensor/elemwise_unary_op_trig.cc      |   40 +-
 src/operator/tensor/histogram-inl.h                |  172 ++
 src/operator/tensor/histogram.cc                   |  159 ++
 src/operator/tensor/histogram.cu                   |  111 ++
 src/operator/tensor/indexing_op-inl.cuh            |    5 +-
 src/operator/tensor/indexing_op.cc                 |   78 +-
 src/operator/tensor/indexing_op.cu                 |   48 +-
 src/operator/tensor/indexing_op.h                  |  504 +++--
 src/operator/tensor/init_op.cu                     |    1 +
 src/operator/tensor/init_op.h                      |    2 +
 src/operator/tensor/matrix_op-inl.h                |  459 ++++-
 src/operator/tensor/matrix_op.cc                   |  107 ++
 src/operator/tensor/matrix_op.cu                   |    6 +
 src/operator/tensor/util/tensor_util-inl.cuh       |    4 +-
 src/storage/pooled_storage_manager.h               |   10 +-
 tests/README.md                                    |   58 +
 tests/cpp/kvstore/gpu_topology_test.cc             |  676 +++++++
 tests/cpp/misc/memory_test.cc                      |  138 --
 tests/cpp/operator/mkldnn.cc                       |  750 +++++++-
 tests/cpp/unittest.mk                              |    8 +-
 tests/jenkins/run_test_installation_docs.sh        |  132 +-
 tests/nightly/Jenkinsfile                          |  181 ++
 tests/nightly/JenkinsfileForBinaries               |  156 ++
 tests/nightly/README.md                            |   49 +-
 tests/nightly/TestDoc/doc_spell_checker.py         |   14 +-
 .../nightly/apache_rat_license_check/.rat-excludes |   55 -
 tests/nightly/apache_rat_license_check/README.md   |    8 +-
 .../nightly/apache_rat_license_check/rat-excludes  |   59 +
 .../broken_link_checker_test/JenkinsfileForBLC     |   92 +
 tests/nightly/broken_link_checker_test/README.md   |   13 +
 .../broken_link_checker.sh                         |   33 +
 .../broken_link_checker_test/check_regression.sh   |   46 +
 .../broken_link_checker_test/test_broken_links.py  |  102 ++
 .../compilation_warnings/compilation_warnings.sh   |    4 +-
 .../nightly/compilation_warnings/process_output.py |   19 +-
 tests/nightly/dist_async_kvstore.py                |   48 +
 tests/nightly/dist_sync_kvstore.py                 |  110 +-
 .../JenkinsfileForMBCC                             |  120 ++
 .../model_backwards_compatibility_check/README.md  |   25 +
 .../model_backwards_compatibility_check/common.py  |  216 +++
 .../model_backward_compat_checker.sh               |   30 +
 .../model_backwards_compat_inference.py            |  137 ++
 .../model_backwards_compat_train.py                |  127 ++
 .../train_mxnet_legacy_models.sh                   |   89 +
 .../upload_models_to_s3.sh                         |   43 +
 tests/nightly/multi_lenet.py                       |    3 +-
 tests/nightly/straight_dope/README.md              |    7 +
 .../straight_dope/straight_dope_test_utils.py      |  157 ++
 .../straight_dope/test_notebooks_multi_gpu.py      |   49 +
 .../straight_dope/test_notebooks_single_gpu.py     |  286 +++
 tests/nightly/test_image_classification.sh         |   35 +-
 tests/python-pytest/onnx/export/backend.py         |   97 +
 tests/python-pytest/onnx/export/backend_rep.py     |   84 +
 .../python-pytest/onnx/export/mxnet_export_test.py |  191 ++
 .../python-pytest/onnx/export/onnx_backend_test.py |  135 ++
 tests/python-pytest/onnx/import/gluon_backend.py   |   13 +-
 .../python-pytest/onnx/import/gluon_backend_rep.py |    1 +
 tests/python-pytest/onnx/import/mxnet_backend.py   |    3 +-
 .../python-pytest/onnx/import/mxnet_backend_rep.py |    4 +-
 tests/python-pytest/onnx/import/test_cases.py      |   44 +-
 tests/python/gpu/test_device.py                    |   82 +
 tests/python/gpu/test_forward.py                   |    6 +-
 tests/python/gpu/test_kvstore_gpu.py               |   61 +-
 tests/python/gpu/test_nccl.py                      |    3 +-
 tests/python/gpu/test_operator_gpu.py              |  274 ++-
 tests/python/mkl/test_mkldnn.py                    |   49 +-
 tests/python/quantization/test_quantization.py     |   28 +-
 tests/python/train/common.py                       |    2 +-
 tests/python/train/test_bucketing.py               |    4 +-
 tests/python/train/test_sparse_fm.py               |  138 ++
 tests/python/unittest/common.py                    |   17 +-
 tests/python/unittest/test_base.py                 |   50 +
 tests/python/unittest/test_contrib_control_flow.py | 1669 +++++++++++++++++
 tests/python/unittest/test_engine_import.py        |    2 +
 tests/python/unittest/test_executor.py             |   26 +-
 tests/python/unittest/test_gluon.py                |  157 +-
 tests/python/unittest/test_gluon_data.py           |   12 +
 tests/python/unittest/test_gluon_rnn.py            |  108 +-
 tests/python/unittest/test_gluon_trainer.py        |   29 +
 tests/python/unittest/test_gluon_utils.py          |   44 +-
 tests/python/unittest/test_image.py                |   54 +-
 tests/python/unittest/test_io.py                   |    9 +-
 tests/python/unittest/test_kvstore.py              |   71 +-
 tests/python/unittest/test_loss.py                 |   13 +-
 tests/python/unittest/test_metric.py               |   49 +
 tests/python/unittest/test_module.py               |   71 +-
 tests/python/unittest/test_ndarray.py              |   85 +-
 tests/python/unittest/test_operator.py             |  747 ++++++--
 tests/python/unittest/test_optimizer.py            |   12 +-
 tests/python/unittest/test_random.py               |    9 +-
 tests/python/unittest/test_sparse_ndarray.py       |   42 +-
 tests/python/unittest/test_sparse_operator.py      |  523 ++++--
 tests/python/unittest/test_symbol.py               |    4 +-
 tests/python/unittest/test_thread_local.py         |   29 +
 tests/python/unittest/test_viz.py                  |   30 +-
 tests/requirements.txt                             |    3 +
 tests/tutorials/test_sanity_tutorials.py           |    4 +-
 tests/tutorials/test_tutorials.py                  |   94 +-
 tests/utils/notebook_test/__init__.py              |   98 +
 tools/accnn/rank_selection.py                      |    4 +-
 tools/accnn/utils.py                               |   11 +-
 tools/caffe_converter/compare_layers.py            |    3 +-
 tools/caffe_converter/convert_symbol.py            |    2 +
 tools/caffe_converter/test_converter.py            |    3 +-
 tools/coreml/converter/_mxnet_converter.py         |    9 +-
 tools/coreml/test/test_mxnet_image.py              |   23 +-
 tools/coreml/test/test_mxnet_models.py             |    8 +-
 tools/flakiness_checker.py                         |  112 ++
 tools/ipynb2md.py                                  |    3 +-
 tools/kill-mxnet.py                                |    9 +-
 tools/license_header.py                            |    2 +-
 913 files changed, 56527 insertions(+), 17964 deletions(-)
 create mode 100644 .codecov.yml
 create mode 100644 MKLDNN_README.md
 delete mode 100644 MKL_README.md
 create mode 100644 R-package/tests/testthat/test_optimizer.R
 create mode 100644 benchmark/python/control_flow/rnn.py
 create mode 100755 ci/build_windows.py
 delete mode 100755 ci/docker/Dockerfile.build.android_arm64
 create mode 100755 ci/docker/Dockerfile.build.android_armv8
 delete mode 100755 ci/docker/Dockerfile.build.arm64
 create mode 100755 ci/docker/Dockerfile.build.armv8
 create mode 100755 ci/docker/Dockerfile.build.ubuntu_base_cpu
 create mode 100755 ci/docker/Dockerfile.build.ubuntu_base_gpu
 create mode 100755 ci/docker/Dockerfile.build.ubuntu_blc
 create mode 100755 ci/docker/Dockerfile.build.ubuntu_nightly_cpu
 create mode 100755 ci/docker/Dockerfile.build.ubuntu_nightly_gpu
 create mode 100755 ci/docker/Dockerfile.build.ubuntu_rat
 delete mode 100755 ci/docker/install/android_arm64_ndk.sh
 create mode 100755 ci/docker/install/android_armv7_openblas.sh
 create mode 100755 ci/docker/install/android_ndk.sh
 create mode 100755 ci/docker/install/export_gpg_keys.sh
 create mode 100644 ci/docker/install/r.gpg
 create mode 100644 ci/docker/install/sbt.gpg
 create mode 100755 ci/docker/install/ubuntu_clojure.sh
 create mode 100755 ci/docker/install/ubuntu_emscripten.sh
 create mode 100755 ci/docker/install/ubuntu_nightly_tests.sh
 create mode 100755 ci/docker/install/ubuntu_npm_blc.sh
 create mode 100755 ci/docker/install/ubuntu_rat.sh
 create mode 100755 ci/docker/install/ubuntu_runas_sudo.sh
 create mode 100644 ci/util.py
 create mode 100644 ci/windows/test_py2_cpu.ps1
 create mode 100644 ci/windows/test_py2_gpu.ps1
 create mode 100644 ci/windows/test_py3_cpu.ps1
 create mode 100644 ci/windows/test_py3_gpu.ps1
 create mode 100644 contrib/clojure-package/.gitignore
 copy {scala-package => contrib/clojure-package}/LICENSE (100%)
 create mode 100644 contrib/clojure-package/README.md
 create mode 100755 contrib/clojure-package/ci-test.sh
 create mode 100644 contrib/clojure-package/examples/cnn-text-classification/.gitignore
 create mode 100644 contrib/clojure-package/examples/cnn-text-classification/README.md
 create mode 100755 contrib/clojure-package/examples/cnn-text-classification/get_data.sh
 create mode 100644 contrib/clojure-package/examples/cnn-text-classification/project.clj
 create mode 100644 contrib/clojure-package/examples/cnn-text-classification/src/cnn_text_classification/classifier.clj
 create mode 100644 contrib/clojure-package/examples/cnn-text-classification/src/cnn_text_classification/data_helper.clj
 create mode 100644 contrib/clojure-package/examples/gan/.gitignore
 create mode 100644 contrib/clojure-package/examples/gan/README.md
 create mode 100644 contrib/clojure-package/examples/gan/project.clj
 create mode 100644 contrib/clojure-package/examples/gan/src/gan/gan_mnist.clj
 create mode 100644 contrib/clojure-package/examples/gan/src/gan/viz.clj
 create mode 100644 contrib/clojure-package/examples/imclassification/.gitignore
 create mode 100644 contrib/clojure-package/examples/imclassification/README.md
 create mode 100644 contrib/clojure-package/examples/imclassification/project.clj
 create mode 100644 contrib/clojure-package/examples/imclassification/src/imclassification/train_mnist.clj
 create mode 100644 contrib/clojure-package/examples/module/README.md
 create mode 100644 contrib/clojure-package/examples/module/project.clj
 create mode 100644 contrib/clojure-package/examples/module/src/mnist_mlp.clj
 create mode 100644 contrib/clojure-package/examples/multi-label/.gitignore
 create mode 100644 contrib/clojure-package/examples/multi-label/README.md
 create mode 100644 contrib/clojure-package/examples/multi-label/project.clj
 create mode 100644 contrib/clojure-package/examples/multi-label/src/multi_label/core.clj
 create mode 100644 contrib/clojure-package/examples/neural-style/.gitignore
 create mode 100644 contrib/clojure-package/examples/neural-style/README.md
 create mode 100755 contrib/clojure-package/examples/neural-style/download.sh
 create mode 100644 contrib/clojure-package/examples/neural-style/project.clj
 create mode 100644 contrib/clojure-package/examples/neural-style/src/neural_style/core.clj
 create mode 100644 contrib/clojure-package/examples/neural-style/src/neural_style/model_vgg_19.clj
 create mode 100644 contrib/clojure-package/examples/pre-trained-models/.gitignore
 create mode 100644 contrib/clojure-package/examples/pre-trained-models/README.md
 create mode 100755 contrib/clojure-package/examples/pre-trained-models/download-caltech.sh
 create mode 100755 contrib/clojure-package/examples/pre-trained-models/download-resnet-152.sh
 create mode 100755 contrib/clojure-package/examples/pre-trained-models/download-resnet-50.sh
 create mode 100644 contrib/clojure-package/examples/pre-trained-models/project.clj
 create mode 100644 contrib/clojure-package/examples/pre-trained-models/src/pre_trained_models/fine_tune.clj
 create mode 100644 contrib/clojure-package/examples/pre-trained-models/src/pre_trained_models/predict_image.clj
 create mode 100644 contrib/clojure-package/examples/profiler/.gitignore
 create mode 100644 contrib/clojure-package/examples/profiler/README.md
 create mode 100644 contrib/clojure-package/examples/profiler/project.clj
 create mode 100644 contrib/clojure-package/examples/profiler/src/profiler/core.clj
 create mode 100644 contrib/clojure-package/examples/rnn/.gitignore
 create mode 100644 contrib/clojure-package/examples/rnn/README.md
 create mode 100755 contrib/clojure-package/examples/rnn/get_data.sh
 create mode 100644 contrib/clojure-package/examples/rnn/project.clj
 create mode 100644 contrib/clojure-package/examples/rnn/src/rnn/lstm.clj
 create mode 100644 contrib/clojure-package/examples/rnn/src/rnn/test_char_rnn.clj
 create mode 100644 contrib/clojure-package/examples/rnn/src/rnn/train_char_rnn.clj
 create mode 100644 contrib/clojure-package/examples/rnn/src/rnn/util.clj
 create mode 100755 contrib/clojure-package/examples/scripts/get_cifar_data.sh
 create mode 100755 contrib/clojure-package/examples/scripts/get_mnist_data.sh
 create mode 100644 contrib/clojure-package/examples/tutorial/.gitignore
 create mode 100644 contrib/clojure-package/examples/tutorial/README.md
 create mode 100644 contrib/clojure-package/examples/tutorial/project.clj
 create mode 100644 contrib/clojure-package/examples/tutorial/src/tutorial/introduction.clj
 create mode 100644 contrib/clojure-package/examples/tutorial/src/tutorial/kvstore.clj
 create mode 100644 contrib/clojure-package/examples/tutorial/src/tutorial/module.clj
 create mode 100644 contrib/clojure-package/examples/tutorial/src/tutorial/ndarray.clj
 create mode 100644 contrib/clojure-package/examples/tutorial/src/tutorial/symbol.clj
 create mode 100644 contrib/clojure-package/examples/visualization/.gitignore
 create mode 100644 contrib/clojure-package/examples/visualization/README.md
 create mode 100644 contrib/clojure-package/examples/visualization/project.clj
 create mode 100644 contrib/clojure-package/examples/visualization/src/visualization/core.clj
 create mode 100755 contrib/clojure-package/lein-cljfmt-check
 create mode 100755 contrib/clojure-package/lein-cljfmt-fix
 create mode 100644 contrib/clojure-package/project.clj
 create mode 100644 contrib/clojure-package/resources/log4j.properties
 create mode 100755 contrib/clojure-package/scripts/get_cifar_data.sh
 create mode 100755 contrib/clojure-package/scripts/get_mnist_data.sh
 create mode 100644 contrib/clojure-package/src/dev/generator.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/base.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/callback.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/context.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/dtype.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/eval_metric.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/executor.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/gen/.gitignore
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/initializer.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/io.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/kvstore.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/kvstore_server.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/lr_scheduler.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/module.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/monitor.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/ndarray.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/optimizer.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/profiler.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/random.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/shape.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/symbol.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/util.clj
 create mode 100644 contrib/clojure-package/src/org/apache/clojure_mxnet/visualization.clj
 create mode 100644 contrib/clojure-package/test/dev/generator_test.clj
 create mode 100644 contrib/clojure-package/test/good-test-ndarray.clj
 create mode 100644 contrib/clojure-package/test/good-test-symbol.clj
 create mode 100644 contrib/clojure-package/test/org/apache/clojure_mxnet/callback_test.clj
 create mode 100644 contrib/clojure-package/test/org/apache/clojure_mxnet/conv_test.clj
 create mode 100644 contrib/clojure-package/test/org/apache/clojure_mxnet/eval_metric_test.clj
 create mode 100644 contrib/clojure-package/test/org/apache/clojure_mxnet/executor_test.clj
 create mode 100644 contrib/clojure-package/test/org/apache/clojure_mxnet/io_test.clj
 create mode 100644 contrib/clojure-package/test/org/apache/clojure_mxnet/kvstore_test.clj
 create mode 100644 contrib/clojure-package/test/org/apache/clojure_mxnet/module_test.clj
 create mode 100644 contrib/clojure-package/test/org/apache/clojure_mxnet/ndarray_test.clj
 create mode 100644 contrib/clojure-package/test/org/apache/clojure_mxnet/operator_test.clj
 create mode 100644 contrib/clojure-package/test/org/apache/clojure_mxnet/optimizer_test.clj
 create mode 100644 contrib/clojure-package/test/org/apache/clojure_mxnet/random_test.clj
 create mode 100644 contrib/clojure-package/test/org/apache/clojure_mxnet/shape_test.clj
 create mode 100644 contrib/clojure-package/test/org/apache/clojure_mxnet/symbol_test.clj
 create mode 100644 contrib/clojure-package/test/org/apache/clojure_mxnet/test_util.clj
 create mode 100644 contrib/clojure-package/test/org/apache/clojure_mxnet/util_test.clj
 create mode 100644 contrib/clojure-package/testing.md
 create mode 100644 docs/api/clojure/index.md
 create mode 100644 docs/api/clojure/kvstore.md
 create mode 100644 docs/api/clojure/module.md
 create mode 100644 docs/api/clojure/ndarray.md
 create mode 100644 docs/api/clojure/symbol.md
 create mode 100644 docs/api/clojure/symbol_in_pictures.md
 create mode 100644 docs/build_version_doc/requirements.txt
 create mode 100644 docs/community/ecosystem.md
 create mode 100644 docs/faq/float16.md
 create mode 100755 docs/install/install_mxnet_ubuntu_python.sh
 create mode 100755 docs/install/install_mxnet_ubuntu_r.sh
 create mode 100644 docs/install/requirements.txt
 create mode 100644 docs/install/scala_setup.md
 create mode 100644 docs/tutorials/gluon/learning_rate_finder.md
 create mode 100644 docs/tutorials/gluon/learning_rate_schedules.md
 create mode 100644 docs/tutorials/gluon/learning_rate_schedules_advanced.md
 create mode 100644 docs/tutorials/gluon/logistic_regression_explained.md
 delete mode 100644 docs/tutorials/scala/README.md
 create mode 100644 docs/tutorials/scala/index.md
 delete mode 100644 example/model-parallel/lstm/README.md
 delete mode 100755 example/model-parallel/lstm/get_ptb_data.sh
 delete mode 100644 example/model-parallel/lstm/lstm.py
 delete mode 100644 example/model-parallel/lstm/lstm_ptb.py
 create mode 100644 example/named_entity_recognition/README.md
 create mode 100644 example/named_entity_recognition/src/iterators.py
 create mode 100644 example/named_entity_recognition/src/metrics.py
 create mode 100644 example/named_entity_recognition/src/ner.py
 create mode 100644 example/named_entity_recognition/src/preprocess.py
 delete mode 100644 example/rcnn/.gitignore
 delete mode 100644 example/rcnn/Makefile
 delete mode 100644 example/rcnn/rcnn/__init__.py
 delete mode 100644 example/rcnn/rcnn/config.py
 delete mode 100644 example/rcnn/rcnn/core/__init__.py
 delete mode 100644 example/rcnn/rcnn/core/callback.py
 delete mode 100644 example/rcnn/rcnn/core/loader.py
 delete mode 100644 example/rcnn/rcnn/core/metric.py
 delete mode 100644 example/rcnn/rcnn/core/module.py
 delete mode 100644 example/rcnn/rcnn/core/tester.py
 delete mode 100644 example/rcnn/rcnn/cython/.gitignore
 delete mode 100644 example/rcnn/rcnn/cython/__init__.py
 delete mode 100644 example/rcnn/rcnn/cython/bbox.pyx
 delete mode 100644 example/rcnn/rcnn/cython/cpu_nms.pyx
 delete mode 100644 example/rcnn/rcnn/cython/gpu_nms.hpp
 delete mode 100644 example/rcnn/rcnn/cython/gpu_nms.pyx
 delete mode 100644 example/rcnn/rcnn/cython/nms_kernel.cu
 delete mode 100644 example/rcnn/rcnn/cython/setup.py
 delete mode 100644 example/rcnn/rcnn/dataset/__init__.py
 delete mode 100644 example/rcnn/rcnn/dataset/coco.py
 delete mode 100644 example/rcnn/rcnn/dataset/ds_utils.py
 delete mode 100644 example/rcnn/rcnn/dataset/imdb.py
 delete mode 100644 example/rcnn/rcnn/dataset/pascal_voc.py
 delete mode 100644 example/rcnn/rcnn/dataset/pascal_voc_eval.py
 delete mode 100644 example/rcnn/rcnn/io/__init__.py
 delete mode 100644 example/rcnn/rcnn/io/image.py
 delete mode 100644 example/rcnn/rcnn/io/rcnn.py
 delete mode 100644 example/rcnn/rcnn/io/rpn.py
 delete mode 100644 example/rcnn/rcnn/processing/bbox_regression.py
 delete mode 100644 example/rcnn/rcnn/processing/bbox_transform.py
 delete mode 100644 example/rcnn/rcnn/processing/generate_anchor.py
 delete mode 100644 example/rcnn/rcnn/processing/nms.py
 delete mode 100644 example/rcnn/rcnn/pycocotools/UPSTREAM_REV
 delete mode 100644 example/rcnn/rcnn/pycocotools/__init__.py
 delete mode 100644 example/rcnn/rcnn/pycocotools/_mask.pyx
 delete mode 100644 example/rcnn/rcnn/pycocotools/coco.py
 delete mode 100644 example/rcnn/rcnn/pycocotools/cocoeval.py
 delete mode 100644 example/rcnn/rcnn/pycocotools/mask.py
 delete mode 100644 example/rcnn/rcnn/pycocotools/maskApi.c
 delete mode 100644 example/rcnn/rcnn/pycocotools/maskApi.h
 delete mode 100644 example/rcnn/rcnn/pycocotools/setup.py
 delete mode 100644 example/rcnn/rcnn/symbol/__init__.py
 delete mode 100644 example/rcnn/rcnn/symbol/proposal.py
 delete mode 100644 example/rcnn/rcnn/symbol/proposal_target.py
 delete mode 100644 example/rcnn/rcnn/symbol/symbol_resnet.py
 delete mode 100644 example/rcnn/rcnn/symbol/symbol_vgg.py
 delete mode 100644 example/rcnn/rcnn/tools/reeval.py
 delete mode 100644 example/rcnn/rcnn/tools/test_rcnn.py
 delete mode 100644 example/rcnn/rcnn/tools/test_rpn.py
 delete mode 100644 example/rcnn/rcnn/tools/train_rcnn.py
 delete mode 100644 example/rcnn/rcnn/tools/train_rpn.py
 delete mode 100644 example/rcnn/rcnn/utils/combine_model.py
 delete mode 100644 example/rcnn/rcnn/utils/load_data.py
 delete mode 100644 example/rcnn/rcnn/utils/load_model.py
 delete mode 100644 example/rcnn/rcnn/utils/save_model.py
 delete mode 100755 example/rcnn/script/additional_deps.sh
 delete mode 100755 example/rcnn/script/get_coco.sh
 delete mode 100755 example/rcnn/script/get_pretrained_model.sh
 delete mode 100755 example/rcnn/script/get_selective_search.sh
 delete mode 100755 example/rcnn/script/get_voc.sh
 delete mode 100755 example/rcnn/script/resnet_voc07.sh
 delete mode 100755 example/rcnn/script/resnet_voc0712.sh
 delete mode 100755 example/rcnn/script/vgg_alter_voc07.sh
 delete mode 100755 example/rcnn/script/vgg_fast_rcnn.sh
 delete mode 100755 example/rcnn/script/vgg_voc07.sh
 delete mode 100755 example/rcnn/script/vgg_voc0712.sh
 rename example/rcnn/{rcnn/utils => symdata}/__init__.py (100%)
 create mode 100644 example/rcnn/symdata/anchor.py
 create mode 100644 example/rcnn/symdata/bbox.py
 create mode 100644 example/rcnn/symdata/image.py
 create mode 100644 example/rcnn/symdata/loader.py
 create mode 100644 example/rcnn/symdata/vis.py
 rename example/rcnn/{rcnn/tools => symimdb}/__init__.py (100%)
 create mode 100644 example/rcnn/symimdb/coco.py
 create mode 100644 example/rcnn/symimdb/imdb.py
 create mode 100644 example/rcnn/symimdb/pascal_voc.py
 rename example/rcnn/{rcnn/processing => symnet}/__init__.py (100%)
 rename example/rcnn/{rcnn => symnet}/logger.py (100%)
 create mode 100644 example/rcnn/symnet/metric.py
 create mode 100644 example/rcnn/symnet/model.py
 create mode 100644 example/rcnn/symnet/proposal_target.py
 create mode 100644 example/rcnn/symnet/symbol_resnet.py
 create mode 100644 example/rcnn/symnet/symbol_vgg.py
 create mode 100644 example/rcnn/train.py
 delete mode 100644 example/rcnn/train_alternate.py
 delete mode 100644 example/rcnn/train_end2end.py
 delete mode 100755 example/rnn-time-major/get_ptb_data.sh
 create mode 100755 example/rnn-time-major/get_sherlockholmes_data.sh
 delete mode 100755 example/rnn/bucketing/get_ptb_data.sh
 create mode 100755 example/rnn/bucketing/get_sherlockholmes_data.sh
 create mode 100644 example/rnn/large_word_lm/LogUniformGenerator.cc
 create mode 100644 example/rnn/large_word_lm/LogUniformGenerator.h
 create mode 100644 example/rnn/large_word_lm/Makefile
 create mode 100644 example/rnn/large_word_lm/log_uniform.pyx
 create mode 100644 example/rnn/large_word_lm/sampler.py
 create mode 100644 example/rnn/large_word_lm/setup.py
 delete mode 100755 example/rnn/old/get_ptb_data.sh
 create mode 100755 example/rnn/old/get_sherlockholmes_data.sh
 delete mode 100644 example/rnn/old/lstm_ptb.R
 create mode 100644 example/rnn/old/lstm_sherlockholmes.R
 delete mode 100755 example/rnn/word_lm/get_ptb_data.sh
 create mode 100755 example/rnn/word_lm/get_sherlockholmes_data.sh
 create mode 100644 mkldnn.mk
 create mode 100644 perl-package/AI-MXNet-Gluon-Contrib/Changes
 create mode 100644 perl-package/AI-MXNet-Gluon-Contrib/MANIFEST
 create mode 100644 perl-package/AI-MXNet-Gluon-Contrib/META.json
 create mode 100644 perl-package/AI-MXNet-Gluon-Contrib/META.yml
 create mode 100644 perl-package/AI-MXNet-Gluon-Contrib/Makefile.PL
 create mode 100644 perl-package/AI-MXNet-Gluon-Contrib/README
 create mode 100644 perl-package/AI-MXNet-Gluon-Contrib/lib/AI/MXNet/Gluon/Contrib.pm
 create mode 100644 perl-package/AI-MXNet-Gluon-Contrib/lib/AI/MXNet/Gluon/Contrib/NN/BasicLayers.pm
 create mode 100644 perl-package/AI-MXNet-Gluon-Contrib/t/AI-MXNet-Gluon-Contrib.t
 create mode 100644 perl-package/AI-MXNet-Gluon-ModelZoo/Changes
 create mode 100644 perl-package/AI-MXNet-Gluon-ModelZoo/MANIFEST
 create mode 100644 perl-package/AI-MXNet-Gluon-ModelZoo/META.json
 create mode 100644 perl-package/AI-MXNet-Gluon-ModelZoo/META.yml
 create mode 100644 perl-package/AI-MXNet-Gluon-ModelZoo/Makefile.PL
 create mode 100644 perl-package/AI-MXNet-Gluon-ModelZoo/README
 create mode 100755 perl-package/AI-MXNet-Gluon-ModelZoo/examples/image_classification.pl
 create mode 100644 perl-package/AI-MXNet-Gluon-ModelZoo/lib/AI/MXNet/Gluon/ModelZoo.pm
 create mode 100644 perl-package/AI-MXNet-Gluon-ModelZoo/lib/AI/MXNet/Gluon/ModelZoo/ModelStore.pm
 create mode 100644 perl-package/AI-MXNet-Gluon-ModelZoo/lib/AI/MXNet/Gluon/ModelZoo/Vision.pm
 create mode 100644 perl-package/AI-MXNet-Gluon-ModelZoo/lib/AI/MXNet/Gluon/ModelZoo/Vision/AlexNet.pm
 create mode 100644 perl-package/AI-MXNet-Gluon-ModelZoo/lib/AI/MXNet/Gluon/ModelZoo/Vision/DenseNet.pm
 create mode 100644 perl-package/AI-MXNet-Gluon-ModelZoo/lib/AI/MXNet/Gluon/ModelZoo/Vision/Inception.pm
 create mode 100644 perl-package/AI-MXNet-Gluon-ModelZoo/lib/AI/MXNet/Gluon/ModelZoo/Vision/MobileNet.pm
 create mode 100644 perl-package/AI-MXNet-Gluon-ModelZoo/lib/AI/MXNet/Gluon/ModelZoo/Vision/ResNet.pm
 create mode 100644 perl-package/AI-MXNet-Gluon-ModelZoo/lib/AI/MXNet/Gluon/ModelZoo/Vision/SqueezeNet.pm
 create mode 100644 perl-package/AI-MXNet-Gluon-ModelZoo/lib/AI/MXNet/Gluon/ModelZoo/Vision/VGG.pm
 create mode 100644 perl-package/AI-MXNet-Gluon-ModelZoo/t/AI-MXNet-Gluon-ModelZoo.t
 create mode 100644 perl-package/AI-MXNet-Gluon-ModelZoo/t/test_gluon_model_zoo.t
 delete mode 100755 perl-package/AI-MXNet/examples/get_ptb_data.sh
 create mode 100755 perl-package/AI-MXNet/examples/get_sherlockholmes_data.sh
 create mode 100644 perl-package/AI-MXNet/examples/gluon/style_transfer/README.md
 create mode 100755 perl-package/AI-MXNet/examples/gluon/style_transfer/get_data.sh
 create mode 100644 perl-package/AI-MXNet/examples/gluon/style_transfer/net.pl
 create mode 100755 perl-package/AI-MXNet/examples/gluon/style_transfer/style_transfer.pl
 create mode 100644 perl-package/AI-MXNet/examples/gluon/style_transfer/utils.pl
 create mode 100644 perl-package/AI-MXNet/lib/AI/MXNet/Engine.pm
 create mode 100644 perl-package/AI-MXNet/lib/AI/MXNet/Gluon/NN/Activation.pm
 create mode 100644 perl-package/AI-MXNet/t/test_engine.t
 create mode 100644 perl-package/AI-MXNet/t/test_gluon_trainer.t
 delete mode 100755 prepare_mkl.sh
 delete mode 100755 prepare_mkldnn.sh
 delete mode 100644 python/mxnet/contrib/onnx/_import/import_helper.py
 delete mode 100644 python/mxnet/contrib/onnx/_import/import_onnx.py
 delete mode 100644 python/mxnet/contrib/onnx/_import/import_to_gluon.py
 delete mode 100644 python/mxnet/contrib/onnx/_import/op_translations.py
 delete mode 100644 python/mxnet/contrib/onnx/_import/translation_utils.py
 create mode 100644 python/mxnet/contrib/onnx/mx2onnx/LICENSE
 create mode 100644 python/mxnet/contrib/onnx/mx2onnx/__init__.py
 create mode 100644 python/mxnet/contrib/onnx/mx2onnx/_export_helper.py
 create mode 100644 python/mxnet/contrib/onnx/mx2onnx/_op_translations.py
 create mode 100644 python/mxnet/contrib/onnx/mx2onnx/export_model.py
 create mode 100644 python/mxnet/contrib/onnx/mx2onnx/export_onnx.py
 rename python/mxnet/contrib/onnx/{_import => onnx2mx}/__init__.py (100%)
 create mode 100644 python/mxnet/contrib/onnx/onnx2mx/_import_helper.py
 create mode 100644 python/mxnet/contrib/onnx/onnx2mx/_op_translations.py
 create mode 100644 python/mxnet/contrib/onnx/onnx2mx/_translation_utils.py
 rename python/mxnet/contrib/onnx/{_import => onnx2mx}/import_model.py (100%)
 create mode 100644 python/mxnet/contrib/onnx/onnx2mx/import_onnx.py
 create mode 100644 python/mxnet/contrib/onnx/onnx2mx/import_to_gluon.py
 create mode 100644 python/mxnet/util.py
 create mode 100644 scala-package/assembly/src/javadoc.xml
 create mode 100644 scala-package/assembly/src/source.xml
 create mode 100644 scala-package/core/src/main/scala/org/apache/mxnet/NDArrayCollector.scala
 create mode 100644 scala-package/core/src/test/scala/org/apache/mxnet/NDArrayCollectorSuite.scala
 create mode 100755 scala-package/dev/compile-mxnet-backend.sh
 create mode 100644 scala-package/examples/src/main/scala/org/apache/mxnetexamples/Util.scala
 create mode 100644 scala-package/examples/src/main/scala/org/apache/mxnetexamples/cnntextclassification/README.md
 create mode 100644 scala-package/examples/src/main/scala/org/apache/mxnetexamples/customop/README.md
 create mode 100644 scala-package/examples/src/main/scala/org/apache/mxnetexamples/gan/README.md
 create mode 100644 scala-package/examples/src/main/scala/org/apache/mxnetexamples/imclassification/README.md
 create mode 100644 scala-package/examples/src/main/scala/org/apache/mxnetexamples/neuralstyle/README.md
 delete mode 100644 scala-package/examples/src/main/scala/org/apache/mxnetexamples/neuralstyle/end2end/ModelVgg19.scala
 create mode 100644 scala-package/examples/src/test/scala/org/apache/mxnetexamples/cnntextclassification/CNNClassifierExampleSuite.scala
 create mode 100644 scala-package/examples/src/test/scala/org/apache/mxnetexamples/customop/CustomOpExampleSuite.scala
 create mode 100644 scala-package/examples/src/test/scala/org/apache/mxnetexamples/gan/GanExampleSuite.scala
 create mode 100644 scala-package/examples/src/test/scala/org/apache/mxnetexamples/imclassification/MNISTExampleSuite.scala
 create mode 100644 scala-package/examples/src/test/scala/org/apache/mxnetexamples/multitask/MultiTaskSuite.scala
 create mode 100644 scala-package/examples/src/test/scala/org/apache/mxnetexamples/neuralstyle/NeuralStyleSuite.scala
 create mode 100644 scala-package/examples/src/test/scala/org/apache/mxnetexamples/profiler/ProfilerSuite.scala
 create mode 100644 scala-package/mxnet-demo/Makefile
 create mode 100644 scala-package/mxnet-demo/README.md
 create mode 100644 scala-package/mxnet-demo/bin/demo.sh
 create mode 100644 scala-package/mxnet-demo/bin/run_im.sh
 create mode 100644 scala-package/mxnet-demo/pom.xml
 create mode 100644 scala-package/mxnet-demo/src/main/scala/sample/HelloWorld.scala
 create mode 100644 scala-package/mxnet-demo/src/main/scala/sample/ImageClassificationExample.scala
 create mode 100644 src/kvstore/comm_tree.h
 create mode 100644 src/kvstore/gpu_topology.h
 create mode 100644 src/nnvm/graph_editor.cc
 create mode 100644 src/operator/contrib/sync_batch_norm-inl.h
 create mode 100644 src/operator/contrib/sync_batch_norm.cc
 create mode 100644 src/operator/contrib/sync_batch_norm.cu
 create mode 100644 src/operator/control_flow.cc
 create mode 100644 src/operator/subgraph_op_common.cc
 create mode 100644 src/operator/subgraph_op_common.h
 create mode 100644 src/operator/tensor/diag_op-inl.h
 create mode 100644 src/operator/tensor/diag_op.cc
 create mode 100644 src/operator/tensor/diag_op.cu
 create mode 100644 src/operator/tensor/elemwise_binary_broadcast_op-inl.cuh
 create mode 100644 src/operator/tensor/histogram-inl.h
 create mode 100644 src/operator/tensor/histogram.cc
 create mode 100644 src/operator/tensor/histogram.cu
 create mode 100644 tests/README.md
 create mode 100644 tests/cpp/kvstore/gpu_topology_test.cc
 delete mode 100644 tests/cpp/misc/memory_test.cc
 create mode 100755 tests/nightly/Jenkinsfile
 create mode 100755 tests/nightly/JenkinsfileForBinaries
 mode change 100644 => 100755 tests/nightly/README.md
 delete mode 100644 tests/nightly/apache_rat_license_check/.rat-excludes
 mode change 100644 => 100755 tests/nightly/apache_rat_license_check/README.md
 create mode 100755 tests/nightly/apache_rat_license_check/rat-excludes
 create mode 100755 tests/nightly/broken_link_checker_test/JenkinsfileForBLC
 create mode 100755 tests/nightly/broken_link_checker_test/README.md
 create mode 100755 tests/nightly/broken_link_checker_test/broken_link_checker.sh
 create mode 100755 tests/nightly/broken_link_checker_test/check_regression.sh
 create mode 100755 tests/nightly/broken_link_checker_test/test_broken_links.py
 mode change 100644 => 100755 tests/nightly/compilation_warnings/compilation_warnings.sh
 mode change 100644 => 100755 tests/nightly/compilation_warnings/process_output.py
 create mode 100644 tests/nightly/dist_async_kvstore.py
 create mode 100644 tests/nightly/model_backwards_compatibility_check/JenkinsfileForMBCC
 create mode 100644 tests/nightly/model_backwards_compatibility_check/README.md
 create mode 100644 tests/nightly/model_backwards_compatibility_check/common.py
 create mode 100755 tests/nightly/model_backwards_compatibility_check/model_backward_compat_checker.sh
 create mode 100644 tests/nightly/model_backwards_compatibility_check/model_backwards_compat_inference.py
 create mode 100644 tests/nightly/model_backwards_compatibility_check/model_backwards_compat_train.py
 create mode 100755 tests/nightly/model_backwards_compatibility_check/train_mxnet_legacy_models.sh
 create mode 100755 tests/nightly/model_backwards_compatibility_check/upload_models_to_s3.sh
 create mode 100755 tests/nightly/straight_dope/README.md
 create mode 100644 tests/nightly/straight_dope/straight_dope_test_utils.py
 create mode 100644 tests/nightly/straight_dope/test_notebooks_multi_gpu.py
 create mode 100644 tests/nightly/straight_dope/test_notebooks_single_gpu.py
 create mode 100644 tests/python-pytest/onnx/export/backend.py
 create mode 100644 tests/python-pytest/onnx/export/backend_rep.py
 create mode 100644 tests/python-pytest/onnx/export/mxnet_export_test.py
 create mode 100644 tests/python-pytest/onnx/export/onnx_backend_test.py
 create mode 100644 tests/python/gpu/test_device.py
 create mode 100644 tests/python/train/test_sparse_fm.py
 create mode 100644 tests/python/unittest/test_base.py
 create mode 100644 tests/python/unittest/test_contrib_control_flow.py
 create mode 100644 tests/requirements.txt
 create mode 100644 tests/utils/notebook_test/__init__.py
 create mode 100644 tools/flakiness_checker.py


[incubator-mxnet] 02/04: Fix duplicate entry bugs (#11767)

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

reminisce pushed a commit to branch subgraph
in repository https://gitbox.apache.org/repos/asf/incubator-mxnet.git

commit 6393058a0a053538a92cd8402bec62ed27b6d581
Author: reminisce <wu...@gmail.com>
AuthorDate: Tue Jul 17 22:57:13 2018 -0700

    Fix duplicate entry bugs (#11767)
---
 src/operator/subgraph/partition_graph.cc  | 6 +++++-
 tests/python/unittest/test_subgraph_op.py | 8 ++++++++
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/src/operator/subgraph/partition_graph.cc b/src/operator/subgraph/partition_graph.cc
index 11af49a..c935c8f 100644
--- a/src/operator/subgraph/partition_graph.cc
+++ b/src/operator/subgraph/partition_graph.cc
@@ -622,6 +622,10 @@ void TopSortEntries(const Graph& g,
     if (visited.count(node) == 0U) {
       s.emplace(node, 0U, &e);
       visited.insert(node);
+    } else {
+      // The entry's source node has been visited before.
+      // Marking the order for it.
+      entry_top_order_map->emplace(&e, entry_top_order_map->size());
     }
     while (!s.empty()) {
       auto& top = s.top();
@@ -641,7 +645,7 @@ void TopSortEntries(const Graph& g,
           visited.insert(input_node);
         } else {
           // The entry's source node has been visited before.
-          // Marking order for it.
+          // Marking the order for it.
           entry_top_order_map->emplace(&entry, entry_top_order_map->size());
         }
       }
diff --git a/tests/python/unittest/test_subgraph_op.py b/tests/python/unittest/test_subgraph_op.py
index f08c42c..0e5c1e0 100644
--- a/tests/python/unittest/test_subgraph_op.py
+++ b/tests/python/unittest/test_subgraph_op.py
@@ -124,10 +124,18 @@ def test_input_name_order():
         check_input_order(ret, ['exp', 'BatchNorm'])
         check_input_order(ret, ['BatchNorm'])
 
+    def test_network_structure_5():
+        # the last op has multiple duplicate outputs
+        data = mx.sym.var('data')
+        ret = mx.sym.exp(data)
+        ret = mx.sym.Group([ret, ret, ret])
+        check_input_order(ret, ['exp'])
+
     test_network_structure_1()
     test_network_structure_2()
     test_network_structure_3()
     test_network_structure_4()
+    test_network_structure_5()
 
 
 if __name__ == '__main__':


[incubator-mxnet] 04/04: [DO NOT REVIEW] Fix bug of eliminating cycles (#11907)

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

reminisce pushed a commit to branch subgraph
in repository https://gitbox.apache.org/repos/asf/incubator-mxnet.git

commit 6acf6cce1c64ff0a11f91f4e9b9e3588211e4e12
Author: reminisce <wu...@gmail.com>
AuthorDate: Thu Jul 26 21:01:32 2018 -0700

    [DO NOT REVIEW] Fix bug of eliminating cycles (#11907)
    
    * Fix cycle bug
    
    * Fix decycle bug
    
    * Fix comment
---
 src/operator/subgraph/partition_graph.cc  | 71 +++++++++++++++++++++++++++----
 tests/python/unittest/test_subgraph_op.py | 11 +++++
 2 files changed, 74 insertions(+), 8 deletions(-)

diff --git a/src/operator/subgraph/partition_graph.cc b/src/operator/subgraph/partition_graph.cc
index 0546430..9672877 100644
--- a/src/operator/subgraph/partition_graph.cc
+++ b/src/operator/subgraph/partition_graph.cc
@@ -147,9 +147,12 @@ bool LabelSubgraph(const Graph& g,
   // key: nodes that serve as input/output nodes to the subgraph
   // value: pair of vectors of nodes in the subgraph. The first vector contains the
   // output nodes of the key in the subgraph, and the second vector contains the
-  // input ndoes of the key in the subgraph. If both vectors are non-empty,
-  // it means there is a loop between the subgraph and the key node.
-  // When breaking the loop, we want to start removing the node with the largest node id.
+  // input nodes of the key in the subgraph.
+  // If a non-subgraph node has inputs from the subgraph and the other non-subgraph node
+  // has outputs to the subgraph, and the first non-subgraph node is an ancestor
+  // of the second non-subgraph node, there exits a cycle.
+  // When breaking the cycle, we want to start from removing the node with the largest node id
+  // in the subgraph.
   std::unordered_map<const nnvm::Node*,
     std::pair<std::vector<const nnvm::Node*>,
               std::vector<const nnvm::Node*>>> non_subgraph_node_map;
@@ -194,23 +197,75 @@ bool LabelSubgraph(const Graph& g,
       }
     }
   }
+  // prepare to check if there is a cycle
   auto node_cmp = [&] (const nnvm::Node* node1, const nnvm::Node* node2) {
     return indexed_graph.node_id(node1) < indexed_graph.node_id(node2);
   };
-  // check whether there is a loop between the subgraph and its input/output nodes
-  int excluded_node_id = -1;
+  std::vector<const nnvm::Node*> non_subgraph_nodes;
+  non_subgraph_nodes.reserve(non_subgraph_node_map.size());
   for (auto& kv : non_subgraph_node_map) {
     auto& output_nodes = kv.second.first;
+    std::sort(output_nodes.begin(), output_nodes.end(), node_cmp);
     auto& input_nodes = kv.second.second;
+    std::sort(input_nodes.begin(), input_nodes.end(), node_cmp);
+    non_subgraph_nodes.push_back(kv.first);
+  }
+  // check whether there is a cycle between the subgraph and its input/output nodes
+  auto is_ancestor = [&](const nnvm::Node* ancestor, const nnvm::Node* descendant,
+                         const std::vector<nnvm::Node*>& snodes) {
+    if (ancestor == descendant) return true;
+    std::stack<const nnvm::Node*> s;
+    s.push(descendant);
+    size_t count = 0;
+    while (!s.empty()) {
+      CHECK_LT(count, indexed_graph.num_nodes()) << "Finding ancestor failed. There is probably"
+                                                    " a loop in the graph";
+      ++count;
+      const nnvm::Node* top = s.top();
+      s.pop();
+      if (top == ancestor) {
+        return true;
+      }
+      for (const auto& entry : top->inputs) {
+        // when searching for the ancestor, the path cannot cross any subgraph node
+        auto it = std::find(snodes.begin(), snodes.end(), entry.node.get());
+        if (it == snodes.end()) {
+          s.push(entry.node.get());
+        }
+      }
+    }
+    return false;
+  };
+  std::sort(non_subgraph_nodes.begin(), non_subgraph_nodes.end(), node_cmp);
+  int excluded_node_id = -1;
+  for (size_t i = 0; i < non_subgraph_nodes.size(); ++i) {
+    auto it1 = non_subgraph_node_map.find(non_subgraph_nodes[i]);
+    CHECK(it1 != non_subgraph_node_map.end());
+    auto& output_nodes = it1->second.first;  // has been top sorted
+    auto& input_nodes = it1->second.second;  // has been top sorted
     if (!output_nodes.empty() && !input_nodes.empty()) {
-      // there is a loop between kv->first and the subgraph
-      std::sort(output_nodes.begin(), output_nodes.end(), node_cmp);
-      std::sort(input_nodes.begin(), input_nodes.end(), node_cmp);
+      // there is a loop between node i and the subgraph
       const auto node_id = std::max(indexed_graph.node_id(output_nodes.back()),
                                     indexed_graph.node_id(input_nodes.back()));
       excluded_node_id = std::max(excluded_node_id, static_cast<int>(node_id));
+    } else if (!input_nodes.empty()) {
+      // node i is an input to the subgraph, find out if there is a node j
+      // which is an output of the subgraph and also a child of node i.
+      for (size_t j = i + 1; j < non_subgraph_nodes.size(); ++j) {
+        auto it2 = non_subgraph_node_map.find(non_subgraph_nodes[j]);
+        CHECK(it2 != non_subgraph_node_map.end());
+        // i is topologically before j, j might be a direct/indirect output node of i
+        CHECK_LT(indexed_graph.node_id(it1->first), indexed_graph.node_id(it2->first));
+        if (!it2->second.first.empty() && is_ancestor(it1->first, it2->first, *subgraph_nodes)) {
+          // found a loop
+          const auto node_id = std::max(indexed_graph.node_id(input_nodes.back()),
+                                        indexed_graph.node_id(it2->second.first.back()));
+          excluded_node_id = std::max(excluded_node_id, static_cast<int>(node_id));
+        }
+      }
     }
   }
+
   if (excluded_node_id != -1) {
     CHECK_LT(excluded_node_id, static_cast<int>(simple_nodes.size()));
     CHECK_NE(excluded_node_id, static_cast<int>(snid))
diff --git a/tests/python/unittest/test_subgraph_op.py b/tests/python/unittest/test_subgraph_op.py
index c3b408b..f6a33c2 100644
--- a/tests/python/unittest/test_subgraph_op.py
+++ b/tests/python/unittest/test_subgraph_op.py
@@ -114,12 +114,23 @@ def test_subgraph_exe():
         for sym, op_names in get_graph():
             check_subgraph_exe(sym, op_names)
 
+    def test_network_structure_7():
+        # in this graph, the subgraph node and the other two external nodes form a cycle
+        data = mx.sym.Variable('data', shape=(1,))
+        ret1 = mx.sym.sin(data)
+        ret2 = mx.sym.cos(ret1)
+        for _ in range(5):
+            ret2 = mx.sym.cos(ret2)
+        ret = ret1 + ret2
+        check_subgraph_exe(ret, ['sin', 'elemwise_add', '_plus', '_Plus'])
+
     test_network_structure_1()
     test_network_structure_2()
     test_network_structure_3()
     test_network_structure_4()
     test_network_structure_5()
     test_network_structure_6()
+    test_network_structure_7()
 
 
 if __name__ == '__main__':


[incubator-mxnet] 03/04: Make subgraph var node name unique (#11876)

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

reminisce pushed a commit to branch subgraph
in repository https://gitbox.apache.org/repos/asf/incubator-mxnet.git

commit dbf781c916848273aa25a24ae544e9cc5e1c9b26
Author: reminisce <wu...@gmail.com>
AuthorDate: Tue Jul 24 15:46:50 2018 -0700

    Make subgraph var node name unique (#11876)
---
 src/operator/subgraph/partition_graph.cc  |  12 ++-
 tests/python/unittest/test_subgraph_op.py | 144 +++++++++++++-----------------
 2 files changed, 74 insertions(+), 82 deletions(-)

diff --git a/src/operator/subgraph/partition_graph.cc b/src/operator/subgraph/partition_graph.cc
index c935c8f..0546430 100644
--- a/src/operator/subgraph/partition_graph.cc
+++ b/src/operator/subgraph/partition_graph.cc
@@ -410,7 +410,6 @@ void SortEntries(const std::unordered_map<const nnvm::NodeEntry*, size_t>& entry
  * \param entry_top_order_map mapping entry pointer to its top sorted position
  * \param input_entries input entries of the subgraph
  */
-
 void FindInputEntries(const Graph& g,
                       const std::vector<SimpleNodePtr>& simple_nodes,
                       const std::vector<SimpleNode*>& subgraph_nodes,
@@ -517,6 +516,8 @@ void CutGraphInputs(const std::vector<nnvm::NodeEntry*> &input_entries,
                     std::vector<nnvm::NodeEntry> *orig_entries,
                     const bool skip_var = false) {
   orig_entries->resize(input_entries.size());
+  // map for creating unique var nodes for deduplicating entries from the same node
+  std::unordered_map<std::string, int> name_count_map;
   for (size_t i = 0; i < input_entries.size(); ++i) {
     nnvm::NodeEntry *e = input_entries[i];
     // If the node is a variable itself, we may want to skip the node.
@@ -529,7 +530,14 @@ void CutGraphInputs(const std::vector<nnvm::NodeEntry*> &input_entries,
     sym.outputs.push_back(*e);
     const auto output_names = sym.ListOutputNames();
     CHECK_EQ(output_names.size(), 1U);
-    nnvm::NodePtr n = nnvm::CreateVariableNode(output_names[0]);
+    const std::string& var_name = output_names[0];
+    auto it = name_count_map.find(var_name);
+    if (name_count_map.end() == it) {
+      name_count_map.emplace(var_name, 0);
+    } else {
+      ++(it->second);
+    }
+    nnvm::NodePtr n = nnvm::CreateVariableNode(var_name + std::to_string(name_count_map[var_name]));
     *e = nnvm::NodeEntry{n, 0, 0};
   }
 }
diff --git a/tests/python/unittest/test_subgraph_op.py b/tests/python/unittest/test_subgraph_op.py
index 0e5c1e0..c3b408b 100644
--- a/tests/python/unittest/test_subgraph_op.py
+++ b/tests/python/unittest/test_subgraph_op.py
@@ -20,122 +20,106 @@ import mxnet as mx
 from mxnet.base import SymbolHandle, check_call, _LIB, mx_uint, c_str_array
 from mxnet.symbol import Symbol
 import numpy as np
+from mxnet.test_utils import assert_almost_equal
 
 
-def test_subgraph():
-    def get_graph():
-        data1 = mx.sym.Variable('data1', shape=(3, 3, 10, 10), dtype=np.float32)
-        data2 = mx.sym.Variable('data2', shape=(1, 0, 2, 2))
-        data3 = mx.sym.sin(data2)
-        conv = mx.sym.Convolution(data=data1, weight=data3, kernel=(2, 2), num_filter=1)
-        rets = []
-        rets.append((conv, []))
-        rets.append((conv, [mx.sym.sin.__name__]))
-        rets.append((conv, [mx.sym.Convolution.__name__]))
-        rets.append((conv, [mx.sym.sin.__name__, mx.sym.Convolution.__name__]))
-        return rets
-
-    for regular_sym, op_names in get_graph():
-        input_names = regular_sym.list_inputs()
-        shapes = regular_sym.infer_shape()
-        types = regular_sym.infer_type()
-        out = SymbolHandle()
-
-        check_call(_LIB.MXPartitionGraph(regular_sym.handle, mx_uint(len(op_names)),
-            c_str_array(op_names), ctypes.byref(out)))
-        subgraph_sym = Symbol(out)
-        assert input_names == subgraph_sym.list_inputs()
-
-        print(subgraph_sym.list_outputs())
-        assert shapes == subgraph_sym.infer_shape()
-        assert types == subgraph_sym.infer_type()
-
-        regular_exec = regular_sym.simple_bind(ctx=mx.cpu(), grad_req='null')
-        subgraph_exec = subgraph_sym.simple_bind(ctx=mx.cpu(), grad_req='null')
-
-        for name in input_names:
-            regular_exec.arg_dict[name][:] = mx.nd.random.normal(
-                    shape=regular_exec.arg_dict[name].shape)
-            subgraph_exec.arg_dict[name][:] = regular_exec.arg_dict[name]
-
-        subgraph_exec.forward()
-        regular_exec.forward()
-        mx.nd.waitall()
-        assert (subgraph_exec.outputs[0] - regular_exec.outputs[0]).abs().sum().asscalar() == 0.0
-
-
-def test_input_name_order():
-    def check_input_order(sym, op_names):
+def test_subgraph_exe():
+    def check_subgraph_exe(sym, op_names):
         out = SymbolHandle()
         check_call(_LIB.MXPartitionGraph(sym.handle, mx_uint(len(op_names)),
                                          c_str_array(op_names), ctypes.byref(out)))
 
-        new_sym = Symbol(out)
-        #print(sym.list_inputs())
-        #print(new_sym.list_inputs())
-        assert new_sym.list_inputs() == sym.list_inputs()
-        assert new_sym.list_arguments() == sym.list_arguments()
-        assert new_sym.list_auxiliary_states() == sym.list_auxiliary_states()
-        #print(new_sym.list_arguments())
-        #print(new_sym.list_auxiliary_states())
-        #print('original outputs: %s' % sym.list_outputs())
-        #print('new sym outputs: %s' % new_sym.list_outputs())
+        partitioned_sym = Symbol(out)
+        assert partitioned_sym.list_inputs() == sym.list_inputs()
+        assert partitioned_sym.list_arguments() == sym.list_arguments()
+        assert partitioned_sym.list_auxiliary_states() == sym.list_auxiliary_states()
+        exe = sym.simple_bind(ctx=mx.cpu(), grad_req='null')
+        partitioned_exe = partitioned_sym.simple_bind(ctx=mx.cpu(), grad_req='null')
+        input_names = sym.list_inputs()
+        for name in input_names:
+            if name in exe.arg_dict:
+                exe.arg_dict[name][:] = mx.nd.random.uniform(shape=exe.arg_dict[name].shape)
+                partitioned_exe.arg_dict[name][:] = exe.arg_dict[name]
+            else:
+                assert name in exe.aux_dict
+                exe.aux_dict[name][:] = mx.nd.random.uniform(shape=exe.aux_dict[name].shape)
+                partitioned_exe.aux_dict[name][:] = exe.aux_dict[name]
+        exe.forward()
+        partitioned_exe.forward()
+        mx.nd.waitall()
+        assert len(exe.outputs) == len(partitioned_exe.outputs)
+        for i in range(len(exe.outputs)):
+            assert_almost_equal((exe.outputs[i] - partitioned_exe.outputs[i]).abs().sum().asnumpy(),
+                                np.zeros(shape=(1,)))
 
     def test_network_structure_1():
-        data1 = mx.sym.var('data1')
+        data1 = mx.sym.var('data1', shape=(2, 3, 10, 10))
         data2 = mx.sym.var('data2')
         conv1 = mx.sym.Convolution(data=data1, weight=data2, no_bias=True, kernel=(2, 2), num_filter=1)
-        conv2 = mx.sym.Convolution(data=data2, weight=data1, no_bias=True, kernel=(2, 2), num_filter=1)
+        conv2 = mx.sym.Convolution(data=data2, no_bias=True, kernel=(1, 1), num_filter=1)
         out = mx.sym.Group([conv1, conv2])
-        check_input_order(out, ['Convolution'])
+        check_subgraph_exe(out, ['Convolution'])
 
     def test_network_structure_2():
-        data1 = mx.sym.var('data1')
-        data2 = mx.sym.var('data2')
-        conv1 = mx.sym.Convolution(data=data1, weight=data2, no_bias=True, kernel=(2, 2), num_filter=1)
-        conv2 = mx.sym.Convolution(data=data2, weight=data1, no_bias=True, kernel=(2, 2), num_filter=1)
-        out = conv1 + conv2
-        check_input_order(out, ['Convolution'])
-        check_input_order(out, ['Convolution', '_Plus', 'elemwise_add', '_plus'])
-
-    def test_network_structure_3():
         # this tests whether the partitioning algorithm can deal with cycles
-        data = mx.sym.var('data')
+        data = mx.sym.var('data', shape=(2, 3, 10, 10))
         ret = mx.sym.exp(data)
         ret1 = mx.sym.cos(ret)
         ret2 = mx.sym.sin(ret)
         ret = ret1 + ret2
-        check_input_order(ret, ['exp', 'sin', '_Plus', 'elemwise_add', '_plus'])
-        check_input_order(ret, ['exp', 'cos', '_Plus', 'elemwise_add', '_plus'])
+        check_subgraph_exe(ret, ['exp', 'sin', '_Plus', 'elemwise_add', '_plus'])
+        check_subgraph_exe(ret, ['exp', 'cos', '_Plus', 'elemwise_add', '_plus'])
 
-    def test_network_structure_4():
+    def test_network_structure_3():
         # this tests whether the partitioned sym can distinguish in_args and aux_states
-        data = mx.sym.var('data')
+        data = mx.sym.var('data', shape=(2, 3, 10, 10))
         ret = mx.sym.exp(data)
         ret1 = mx.sym.cos(ret)
         ret2 = mx.sym.sin(ret)
         ret = ret1 + ret2
         ret = mx.sym.BatchNorm(ret)
         ret = mx.sym.BatchNorm(ret)
-        check_input_order(ret, ['exp', 'sin', '_Plus', 'elemwise_add', '_plus'])
-        check_input_order(ret, ['exp', 'cos', '_Plus', 'elemwise_add', '_plus'])
-        check_input_order(ret, ['exp', 'sin', '_Plus', 'elemwise_add', '_plus', 'BatchNorm'])
-        check_input_order(ret, ['exp', 'cos', '_Plus', 'elemwise_add', '_plus', 'BatchNorm'])
-        check_input_order(ret, ['exp', 'BatchNorm'])
-        check_input_order(ret, ['BatchNorm'])
+        check_subgraph_exe(ret, ['exp', 'sin', '_Plus', 'elemwise_add', '_plus'])
+        check_subgraph_exe(ret, ['exp', 'cos', '_Plus', 'elemwise_add', '_plus'])
+        check_subgraph_exe(ret, ['exp', 'sin', '_Plus', 'elemwise_add', '_plus', 'BatchNorm'])
+        check_subgraph_exe(ret, ['exp', 'cos', '_Plus', 'elemwise_add', '_plus', 'BatchNorm'])
+        check_subgraph_exe(ret, ['exp', 'BatchNorm'])
+        check_subgraph_exe(ret, ['BatchNorm'])
 
-    def test_network_structure_5():
+    def test_network_structure_4():
         # the last op has multiple duplicate outputs
-        data = mx.sym.var('data')
+        data = mx.sym.var('data', shape=(2, 3, 10, 10))
         ret = mx.sym.exp(data)
         ret = mx.sym.Group([ret, ret, ret])
-        check_input_order(ret, ['exp'])
+        check_subgraph_exe(ret, ['exp'])
+
+    def test_network_structure_5():
+        # the subgraph has two duplicate input entries
+        data = mx.sym.var('data', shape=(2, 3, 10, 10))
+        ret = data + data
+        check_subgraph_exe(ret, ['_plus', '_Plus', 'elemwise_add'])
+
+    def test_network_structure_6():
+        def get_graph():
+            data1 = mx.sym.Variable('data1', shape=(3, 3, 10, 10), dtype=np.float32)
+            data2 = mx.sym.Variable('data2', shape=(1, 0, 2, 2))
+            data3 = mx.sym.sin(data2)
+            conv = mx.sym.Convolution(data=data1, weight=data3, kernel=(2, 2), num_filter=1)
+            rets = [(conv, []),
+                    (conv, [mx.sym.sin.__name__]),
+                    (conv, [mx.sym.Convolution.__name__]),
+                    (conv, [mx.sym.sin.__name__, mx.sym.Convolution.__name__])]
+            return rets
+
+        for sym, op_names in get_graph():
+            check_subgraph_exe(sym, op_names)
 
     test_network_structure_1()
     test_network_structure_2()
     test_network_structure_3()
     test_network_structure_4()
     test_network_structure_5()
+    test_network_structure_6()
 
 
 if __name__ == '__main__':


[incubator-mxnet] 01/04: Graph partitioner and subgraph op (#11251)

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

reminisce pushed a commit to branch subgraph
in repository https://gitbox.apache.org/repos/asf/incubator-mxnet.git

commit 20246bf260348442447c55ea2670a6e59e46eb8d
Author: reminisce <wu...@gmail.com>
AuthorDate: Thu Jun 21 11:40:31 2018 -0700

    Graph partitioner and subgraph op (#11251)
    
    Graph partitioner and subgraph op
---
 example/subgraph_op/common                   |   1 +
 example/subgraph_op/imagenet_inference.py    | 166 +++++++
 include/mxnet/c_api.h                        |   5 +
 include/mxnet/engine.h                       |  22 +-
 include/mxnet/ndarray.h                      |   4 +
 src/c_api/c_api_symbolic.cc                  |  25 +
 src/engine/engine_impl.h                     |  10 +
 src/engine/naive_engine.cc                   |  31 +-
 src/engine/threaded_engine.cc                |  10 +-
 src/engine/threaded_engine.h                 |   1 +
 src/imperative/imperative_utils.h            |   3 +-
 src/ndarray/ndarray.cc                       |   2 +
 src/operator/subgraph/common.h               | 270 +++++++++++
 src/operator/subgraph/default_subgraph_op.cc | 113 +++++
 src/operator/subgraph/default_subgraph_op.cu |  41 ++
 src/operator/subgraph/default_subgraph_op.h  | 127 +++++
 src/operator/subgraph/partition_graph.cc     | 687 +++++++++++++++++++++++++++
 tests/python/gpu/test_operator_gpu.py        |   1 +
 tests/python/unittest/test_gluon_trainer.py  |   1 +
 tests/python/unittest/test_subgraph_op.py    | 135 ++++++
 20 files changed, 1649 insertions(+), 6 deletions(-)

diff --git a/example/subgraph_op/common b/example/subgraph_op/common
new file mode 120000
index 0000000..cafb914
--- /dev/null
+++ b/example/subgraph_op/common
@@ -0,0 +1 @@
+../image-classification/common
\ No newline at end of file
diff --git a/example/subgraph_op/imagenet_inference.py b/example/subgraph_op/imagenet_inference.py
new file mode 100644
index 0000000..8a38cff
--- /dev/null
+++ b/example/subgraph_op/imagenet_inference.py
@@ -0,0 +1,166 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import argparse
+import logging
+import os
+import time
+import mxnet as mx
+from common import modelzoo
+from mxnet import nd
+from mxnet.contrib.quantization import *
+from mxnet.base import _LIB
+
+
+def download_dataset(dataset_url, dataset_dir, logger=None):
+    if logger is not None:
+        logger.info('Downloading dataset for inference from %s to %s' % (dataset_url, dataset_dir))
+    mx.test_utils.download(dataset_url, dataset_dir)
+
+
+def download_model(model_name, logger=None):
+    dir_path = os.path.dirname(os.path.realpath(__file__))
+    model_path = os.path.join(dir_path, 'model')
+    if logger is not None:
+        logger.info('Downloading model %s... into path %s' % (model_name, model_path))
+    return modelzoo.download_model(args.model, os.path.join(dir_path, 'model'))
+
+
+def advance_data_iter(data_iter, n):
+    assert n >= 0
+    if n == 0:
+        return data_iter
+    has_next_batch = True
+    while has_next_batch:
+        try:
+            data_iter.next()
+            n -= 1
+            if n == 0:
+                return data_iter
+        except StopIteration:
+            has_next_batch = False
+
+
+def score(sym, arg_params, aux_params, data, devs, label_name, max_num_examples, logger=None):
+    metrics = [mx.metric.create('acc'),
+               mx.metric.create('top_k_accuracy', top_k=5)]
+    if not isinstance(metrics, list):
+        metrics = [metrics, ]
+    mod = mx.mod.Module(symbol=sym, context=devs, label_names=[label_name, ])
+    mod.bind(for_training=False,
+             data_shapes=data.provide_data,
+             label_shapes=data.provide_label)
+    mod.set_params(arg_params, aux_params)
+
+    tic = time.time()
+    num = 0
+    for batch in data:
+        mod.forward(batch, is_train=False)
+        for m in metrics:
+            mod.update_metric(m, batch.label)
+        num += batch_size
+        if max_num_examples is not None and num >= max_num_examples:
+            break
+
+    speed = num / (time.time() - tic)
+
+    if logger is not None:
+        logger.info('Finished inference with %d images' % num)
+        logger.info('Finished with %f images per second', speed)
+        for m in metrics:
+            logger.info(m.get())
+
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser(description='Score a model on a dataset')
+    parser.add_argument('--model', type=str, choices=['imagenet1k-resnet-152', 'imagenet1k-inception-bn'],
+                        help='currently only supports imagenet1k-resnet-152 or imagenet1k-inception-bn')
+    parser.add_argument('--batch-size', type=int, default=32)
+    parser.add_argument('--label-name', type=str, default='softmax_label')
+    parser.add_argument('--dataset', type=str, required=True, help='dataset path')
+    parser.add_argument('--rgb-mean', type=str, default='0,0,0')
+    parser.add_argument('--image-shape', type=str, default='3,224,224')
+    parser.add_argument('--data-nthreads', type=int, default=60, help='number of threads for data decoding')
+    parser.add_argument('--num-skipped-batches', type=int, default=0, help='skip the number of batches for inference')
+    parser.add_argument('--num-inference-batches', type=int, required=True, help='number of images used for inference')
+    parser.add_argument('--shuffle-dataset', action='store_true', default=True,
+                        help='shuffle the calibration dataset')
+    parser.add_argument('--shuffle-chunk-seed', type=int, default=3982304,
+                        help='shuffling chunk seed, see'
+                             ' https://mxnet.incubator.apache.org/api/python/io/io.html?highlight=imager#mxnet.io.ImageRecordIter'
+                             ' for more details')
+    parser.add_argument('--shuffle-seed', type=int, default=48564309,
+                        help='shuffling seed, see'
+                             ' https://mxnet.incubator.apache.org/api/python/io/io.html?highlight=imager#mxnet.io.ImageRecordIter'
+                             ' for more details')
+
+    args = parser.parse_args()
+
+    logging.basicConfig()
+    logger = logging.getLogger('logger')
+    logger.setLevel(logging.INFO)
+    data_nthreads = args.data_nthreads
+    batch_size = args.batch_size
+    logger.info('batch size = %d for inference' % batch_size)
+
+    rgb_mean = args.rgb_mean
+    logger.info('rgb_mean = %s' % rgb_mean)
+    rgb_mean = [float(i) for i in rgb_mean.split(',')]
+    mean_args = {'mean_r': rgb_mean[0], 'mean_g': rgb_mean[1], 'mean_b': rgb_mean[2]}
+
+    label_name = args.label_name
+    logger.info('label_name = %s' % label_name)
+
+    image_shape = args.image_shape
+    data_shape = tuple([int(i) for i in image_shape.split(',')])
+    logger.info('Input data shape = %s' % str(data_shape))
+
+    dataset = args.dataset
+    download_dataset('http://data.mxnet.io/data/val_256_q90.rec', dataset)
+    logger.info('Dataset for inference: %s' % dataset)
+
+    # creating data iterator
+    data = mx.io.ImageRecordIter(path_imgrec=dataset,
+                                 label_width=1,
+                                 preprocess_threads=data_nthreads,
+                                 batch_size=batch_size,
+                                 data_shape=data_shape,
+                                 label_name=label_name,
+                                 rand_crop=False,
+                                 rand_mirror=False,
+                                 shuffle=True,
+                                 shuffle_chunk_seed=3982304,
+                                 seed=48564309,
+                                 **mean_args)
+
+    # download model
+    prefix, epoch = download_model(model_name=args.model, logger=logger)
+    sym, arg_params, aux_params = mx.model.load_checkpoint(prefix, epoch)
+    op_names = ['BatchNorm', 'Convolution', 'Pooling', 'Activation']
+    out = SymbolHandle()
+    check_call(_LIB.MXPartitionGraph(sym.handle, mx_uint(len(op_names)), c_str_array(op_names),
+                                     ctypes.byref(out)))
+    psym = Symbol(out)
+
+    # make sure that fp32 inference works on the same images as calibrated quantized model
+    logger.info('Skipping the first %d batches' % args.num_skipped_batches)
+    data = advance_data_iter(data, args.num_skipped_batches)
+
+    num_inference_images = args.num_inference_batches * batch_size
+    logger.info('Running model %s for inference' % args.model)
+    score(psym, arg_params, aux_params, data, [mx.gpu(0)], label_name,
+          max_num_examples=num_inference_images, logger=logger)
diff --git a/include/mxnet/c_api.h b/include/mxnet/c_api.h
index 75147cf..2987cd7 100644
--- a/include/mxnet/c_api.h
+++ b/include/mxnet/c_api.h
@@ -1479,6 +1479,11 @@ MXNET_DLL int MXSetCalibTableToQuantizedSymbol(SymbolHandle qsym_handle,
                                                const float* high_quantiles,
                                                SymbolHandle* ret_sym_handle);
 
+MXNET_DLL int MXPartitionGraph(SymbolHandle sym_handle,
+                               const mx_uint num_ops,
+                               const char** op_names,
+                               SymbolHandle* ret_sym_handle);
+
 //--------------------------------------------
 // Part 4: Executor interface
 //--------------------------------------------
diff --git a/include/mxnet/engine.h b/include/mxnet/engine.h
index dc48bfb..2c33b6c 100644
--- a/include/mxnet/engine.h
+++ b/include/mxnet/engine.h
@@ -41,8 +41,26 @@ class Engine;
 
 /*! \brief namespace of engine internal types. */
 namespace engine {
-/*! \brief Internal representation of variable. */
-struct Var;
+/*! \brief base class of engine variables.*/
+struct Var {
+  virtual uint32_t version() {
+    return version_;
+  }
+  virtual ~Var() = default;
+  /*!
+   * \brief cast variable to derived type T
+   * \tparam T the type we want to cast into.
+   * \return A casted variable.
+   */
+  template <typename T>
+  inline T* Cast();
+  /*!
+   * \brief version number of the var. Every time the object it is associated with
+   * is modified, the version number is incremented by 1.
+   */
+  uint32_t version_{0};
+};  // struct Var
+
 /*! \brief Internal representation of operator.  */
 struct Opr;
 /*! \brief Variable pointer type, usually hold by user used to specify dependencies. */
diff --git a/include/mxnet/ndarray.h b/include/mxnet/ndarray.h
index bae3ea9..893302f 100644
--- a/include/mxnet/ndarray.h
+++ b/include/mxnet/ndarray.h
@@ -340,6 +340,10 @@ class NDArray {
   inline size_t byte_offset() const {
     return byte_offset_;
   }
+  /*! \brief return var version of the NDArray*/
+  inline uint32_t version() const {
+    return var()->version();
+  }
   /*!
    * \brief save the content into binary stream
    * \param strm the output stream
diff --git a/src/c_api/c_api_symbolic.cc b/src/c_api/c_api_symbolic.cc
index c27a59a..7ed86ec 100644
--- a/src/c_api/c_api_symbolic.cc
+++ b/src/c_api/c_api_symbolic.cc
@@ -31,6 +31,7 @@
 #include "./c_api_common.h"
 #include "../operator/operator_common.h"
 #include "../executor/exec_pass.h"
+#include "../operator/subgraph/default_subgraph_op.h"
 
 namespace mxnet {
 namespace op {
@@ -696,3 +697,27 @@ int MXSetCalibTableToQuantizedSymbol(SymbolHandle qsym_handle,
   *ret_qsym_handle = s;
   API_END_HANDLE_ERROR(delete s);
 }
+
+int MXPartitionGraph(SymbolHandle sym_handle,
+                     const mx_uint num_ops,
+                     const char** op_names,
+                     SymbolHandle* ret_sym_handle) {
+  nnvm::Symbol* s = new nnvm::Symbol();
+  API_BEGIN();
+  std::unordered_set<std::string> op_name_set;
+  for (size_t i = 0; i < num_ops; ++i) {
+    op_name_set.emplace(op_names[i]);
+  }
+  nnvm::Symbol* sym = static_cast<nnvm::Symbol*>(sym_handle);
+  *s = sym->Copy();
+  nnvm::Graph g = Symbol2Graph(*s);
+  if (!op_name_set.empty()) {
+    mxnet::op::SubgraphPropertyPtr property
+        = std::make_shared<mxnet::op::DefaultSubgraphProperty>(op_name_set);
+    g.attrs["subgraph_property"] = std::make_shared<nnvm::any>(std::move(property));
+  }
+  g = ApplyPass(std::move(g), "PartitionGraph");
+  s->outputs = g.outputs;
+  *ret_sym_handle = s;
+  API_END_HANDLE_ERROR(delete s);
+}
diff --git a/src/engine/engine_impl.h b/src/engine/engine_impl.h
index b3ec34d..9219b91 100644
--- a/src/engine/engine_impl.h
+++ b/src/engine/engine_impl.h
@@ -33,8 +33,12 @@
 namespace mxnet {
 namespace engine {
 
+#if 0
 /*! \brief base class of engine variables, used for type checking */
 struct Var {
+  virtual uint32_t version() {
+    return version_;
+  }
 #if ENGINE_DEBUG
   virtual ~Var() = default;
 #endif  // ENGINE_DEBUG
@@ -45,7 +49,13 @@ struct Var {
    */
   template <typename T>
   inline T* Cast();
+  /*!
+   * \brief version number of the var. Every time the object it is associated with
+   * is modified, the version number is incremented by 1.
+   */
+  uint32_t version_{0};
 };  // struct Var
+#endif
 
 /*! \brief base class of engine operators, used for type checking */
 struct Opr {
diff --git a/src/engine/naive_engine.cc b/src/engine/naive_engine.cc
index 8196af2..e0a47fa 100644
--- a/src/engine/naive_engine.cc
+++ b/src/engine/naive_engine.cc
@@ -28,10 +28,24 @@
 #include "./engine_impl.h"
 #include "../profiler/profiler.h"
 #include "./openmp.h"
+#include "../common/object_pool.h"
 
 namespace mxnet {
 namespace engine {
 
+/*!
+ * \brief var used in Naive Engine for tracking the version
+ * of the objects it is associated with.
+ */
+class NaiveVar final
+    : public Var, public common::ObjectPoolAllocatable<NaiveVar> {
+ public:
+  inline static NaiveVar* CastFromBase(Var* ptr) {
+    return ptr->Cast<NaiveVar>();
+  }
+};  // class NaiveVar
+
+
 // implement naive engine
 class NaiveEngine final : public Engine {
  public:
@@ -71,8 +85,11 @@ class NaiveEngine final : public Engine {
 
   // new variables
   VarHandle NewVariable() override {
+    return NaiveVar::New();
+#if 0
     size_t v = ++counter_;
     return reinterpret_cast<VarHandle>(v);
+#endif
   }
 
   OprHandle NewOperator(AsyncFn fn,
@@ -165,14 +182,26 @@ class NaiveEngine final : public Engine {
     }
     CHECK(this->req_completed_)
         << "NaiveEngine only support synchronize Push so far";
+    // increment var version
+    for (auto var : mutable_vars) {
+      ++var->version_;
+    }
     if (profiling) {
       opr->opr_profile->stop();
     }
   }
 
   void DeleteVariable(SyncFn delete_fn, Context exec_ctx, VarHandle var) override {
+    NaiveVar* naive_var = NaiveVar::CastFromBase(var);
+    this->PushAsync([delete_fn, naive_var](RunContext ctx, CallbackOnComplete on_complete) mutable {
+        delete_fn(ctx);
+        NaiveVar::Delete(naive_var);
+        on_complete();
+      }, exec_ctx, {}, {var}, FnProperty::kDeleteVar, 0, "DeleteVariable");
+#if 0
     this->PushSync(delete_fn, exec_ctx, {}, {var},
                    FnProperty::kNormal, 0, "DeleteVariable");
+#endif
   }
 
   void WaitForVar(VarHandle var) override {
@@ -192,8 +221,6 @@ class NaiveEngine final : public Engine {
   }
   // whether action is completed
   bool req_completed_;
-  // counter
-  std::atomic<size_t> counter_{0};
   /*! \brief whether it is during shutdown phase*/
   std::atomic<bool> shutdown_phase_{false};
   // CPU stream
diff --git a/src/engine/threaded_engine.cc b/src/engine/threaded_engine.cc
index e70cc19..bd11697 100644
--- a/src/engine/threaded_engine.cc
+++ b/src/engine/threaded_engine.cc
@@ -130,6 +130,9 @@ inline bool ThreadedVar::CompleteWriteDependency(Dispatcher dispatcher) {
     assert(pending_write_ != nullptr);
     CHECK_EQ(num_pending_reads_, kWriteTriggered);
 
+    // increment version number
+    ++version_;
+
     // really delete
     if (to_delete_) {
       VersionedVarBlock *head = pending_write_->next;
@@ -164,7 +167,7 @@ inline bool ThreadedVar::CompleteWriteDependency(Dispatcher dispatcher) {
   }
   // This is outside of lock scope
   // Be very carful, pending_write_ and num_pending_reads_
-  // can change now, do not reply ont the two variables.
+  // can change now, do not rely on these two variables.
   // The linked list \in [old_pending_write, end_of_read_chain)
   // is already detached from this Var.
   // So it is safe to modify these
@@ -196,6 +199,11 @@ inline bool ThreadedVar::ready_to_read() {
   return this->is_ready_to_read();
 }
 
+inline uint32_t ThreadedVar::version() {
+  std::lock_guard<std::mutex> lock{mutex_};
+  return this->version_;
+}
+
 // implementation of threaded engine
 ThreadedVar* ThreadedEngine::NewVariable() {
   return ThreadedVar::New(VersionedVarBlock::New());
diff --git a/src/engine/threaded_engine.h b/src/engine/threaded_engine.h
index 428f0d8..7730c06 100644
--- a/src/engine/threaded_engine.h
+++ b/src/engine/threaded_engine.h
@@ -162,6 +162,7 @@ class ThreadedVar final
   inline void SetToDelete();
   /*! \return whether this variable is ready to read. */
   inline bool ready_to_read();
+  inline uint32_t version() override;
   /*!
    * \brief Cast a Var pointer to ThreadedVar pointer
    * \param ptr pointer from base.
diff --git a/src/imperative/imperative_utils.h b/src/imperative/imperative_utils.h
index 9c86843..69fe2c5 100644
--- a/src/imperative/imperative_utils.h
+++ b/src/imperative/imperative_utils.h
@@ -436,7 +436,8 @@ inline void PushFComputeEx(const FComputeEx& fn,
       }
     };
 
-  if (exec_type == ExecType::kCrossDeviceCopy) {
+  if (exec_type == ExecType::kCrossDeviceCopy
+      || exec_type == ExecType::kSubgraphExec) {
     run(RunContext{ctx, nullptr});
   } else {
     CHECK(exec_type == ExecType::kSync);
diff --git a/src/ndarray/ndarray.cc b/src/ndarray/ndarray.cc
index 853838a..1abab80 100644
--- a/src/ndarray/ndarray.cc
+++ b/src/ndarray/ndarray.cc
@@ -39,6 +39,7 @@
 #include "../operator/tensor/matrix_op-inl.h"
 #include "../operator/tensor/init_op.h"
 #include "../operator/nn/mkldnn/mkldnn_base-inl.h"
+#include "../engine/engine_impl.h"
 
 #if MXNET_USE_OPENCV
 #include <opencv2/opencv.hpp>
@@ -1974,6 +1975,7 @@ void NDArray::SyncCheckFormat(const bool full_check) const {
   CHECK_EQ(err, kNormalErr) << "Check the validity of this sparse NDArray";
 }
 
+
 #if MXNET_PREDICT_ONLY == 0
 // register API function
 // those with underscore will be registered at NDArray
diff --git a/src/operator/subgraph/common.h b/src/operator/subgraph/common.h
new file mode 100644
index 0000000..472312d
--- /dev/null
+++ b/src/operator/subgraph/common.h
@@ -0,0 +1,270 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef MXNET_OPERATOR_SUBGRAPH_COMMON_H_
+#define MXNET_OPERATOR_SUBGRAPH_COMMON_H_
+
+#include <string>
+#include <set>
+#include <vector>
+#include "../elemwise_op_common.h"
+#include "../../executor/exec_pass.h"
+
+namespace mxnet {
+namespace op {
+namespace sg {
+
+struct SimpleNode;
+using SimpleNodePtr = std::shared_ptr<SimpleNode>;
+
+/*!
+ * \brief Node of the undirected graph which replicates the network structures
+ * of the computational graph. It is used to ease the graph traversal for finding
+ * subgraphs.
+ */
+struct SimpleNode {
+  static SimpleNodePtr Create() {
+    return std::make_shared<SimpleNode>();
+  }
+  SimpleNode() : label(-1), node(nullptr) {}
+  /*! subgraph label */
+  int label;
+  /*! the original node in the computational graph it references*/
+  nnvm::Node* node;
+  /*!
+   * \brief output nodes of the current node
+   * key is node ptr and value is an array of indices standing for the entry indices
+   * in key->inputs whose source is the current node.
+   */
+  std::unordered_map<nnvm::Node*, std::vector<size_t>> outputs;
+};  // struct SimpleNode
+}  // namespace sg
+
+inline uint32_t DefaultSubgraphOpNumInputs(const nnvm::NodeAttrs& attrs) {
+  const nnvm::Symbol& sym = nnvm::get<nnvm::Symbol>(attrs.parsed);
+  return sym.ListInputNames(nnvm::Symbol::kAll).size();
+}
+
+inline uint32_t DefaultSubgraphOpNumOutputs(const nnvm::NodeAttrs& attrs) {
+  const nnvm::Symbol& sym = nnvm::get<nnvm::Symbol>(attrs.parsed);
+  return sym.ListOutputNames().size();
+}
+
+inline std::vector<std::string> DefaultSubgraphOpListInputs(const nnvm::NodeAttrs& attrs) {
+  const nnvm::Symbol& sym = nnvm::get<nnvm::Symbol>(attrs.parsed);
+  return sym.ListInputNames(nnvm::Symbol::kAll);
+}
+
+inline std::vector<std::string> DefaultSubgraphOpListOutputs(const nnvm::NodeAttrs& attrs) {
+  const nnvm::Symbol& sym = nnvm::get<nnvm::Symbol>(attrs.parsed);
+  return sym.ListOutputNames();
+}
+
+inline bool DefaultSubgraphOpShape(const nnvm::NodeAttrs& attrs,
+                                   std::vector<TShape> *in_shapes,
+                                   std::vector<TShape> *out_shapes) {
+  using namespace exec;
+  const nnvm::Symbol& subgraph_sym = nnvm::get<nnvm::Symbol>(attrs.parsed);
+  nnvm::Graph g;
+  g.outputs = subgraph_sym.outputs;
+  const auto& idx_g = g.indexed_graph();
+  CHECK_EQ(idx_g.input_nodes().size(), in_shapes->size());
+  CHECK_EQ(idx_g.outputs().size(), out_shapes->size());
+
+  // Put the input and output shapes to the shape vector.
+  nnvm::ShapeVector shapes(idx_g.num_node_entries());
+  const auto &input_nids = idx_g.input_nodes();
+  CHECK_EQ(input_nids.size(), in_shapes->size());
+  for (size_t i = 0; i < in_shapes->size(); i++) {
+    auto eid = idx_g.entry_id(input_nids[i], 0);
+    shapes[eid] = in_shapes->at(i);
+  }
+  CHECK_EQ(g.outputs.size(), out_shapes->size());
+  for (size_t i = 0; i < out_shapes->size(); i++) {
+    auto eid = idx_g.entry_id(g.outputs[i]);
+    shapes[eid] = out_shapes->at(i);
+  }
+
+  // Infer shape of the graph.
+  g.attrs["shape"] = std::make_shared<dmlc::any>(std::move(shapes));
+  g = exec::InferShape(std::move(g));
+
+  // Copy the inferred shape back to the input shapes and the output shapes.
+  shapes = g.GetAttr<nnvm::ShapeVector>("shape");
+  // assign to in_shapes
+  for (size_t i = 0; i < in_shapes->size(); ++i) {
+    const auto eid = idx_g.entry_id(input_nids[i], 0);
+    SHAPE_ASSIGN_CHECK(*in_shapes, i, shapes[eid]);
+  }
+  // assign to out_shapes
+  for (size_t i = 0; i < g.outputs.size(); ++i) {
+    const auto eid = idx_g.entry_id(g.outputs[i]);
+    SHAPE_ASSIGN_CHECK(*out_shapes, i, shapes[eid]);
+  }
+  // Check if we have inferred the shapes correctly.
+  return g.GetAttr<size_t>("shape_num_unknown_nodes") == 0;
+}
+
+inline bool DefaultSubgraphOpType(const nnvm::NodeAttrs& attrs,
+                                  std::vector<int> *in_types,
+                                  std::vector<int> *out_types) {
+  const nnvm::Symbol& subgraph_sym = nnvm::get<nnvm::Symbol>(attrs.parsed);
+  nnvm::Graph g;
+  g.outputs = subgraph_sym.outputs;
+  const auto& idx_g = g.indexed_graph();
+  CHECK_EQ(idx_g.input_nodes().size(), in_types->size());
+  CHECK_EQ(idx_g.outputs().size(), out_types->size());
+
+  // Put the input and output data types to the dtype vector.
+  nnvm::DTypeVector types(idx_g.num_node_entries(), -1);
+  const auto &input_nids = idx_g.input_nodes();
+  CHECK_EQ(input_nids.size(), in_types->size());
+  for (size_t i = 0; i < in_types->size(); i++) {
+    auto eid = idx_g.entry_id(input_nids[i], 0);
+    types[eid] = in_types->at(i);
+  }
+  CHECK_EQ(g.outputs.size(), out_types->size());
+  for (size_t i = 0; i < out_types->size(); i++) {
+    auto eid = idx_g.entry_id(g.outputs[i]);
+    types[eid] = out_types->at(i);
+  }
+
+  // Infer data type of the graph.
+  g.attrs["dtype"] = std::make_shared<dmlc::any>(std::move(types));
+  g = exec::InferType(std::move(g));
+
+  types = g.GetAttr<nnvm::DTypeVector>("dtype");
+  // assign to in_types
+  for (size_t i = 0; i < in_types->size(); ++i) {
+    const auto eid = idx_g.entry_id(input_nids[i], 0);
+    TYPE_ASSIGN_CHECK(*in_types, i, types[eid]);
+  }
+  // assign to out_types
+  for (size_t i = 0; i < g.outputs.size(); ++i) {
+    const auto eid = idx_g.entry_id(g.outputs[i]);
+    TYPE_ASSIGN_CHECK(*out_types, i, types[eid]);
+  }
+  // Check if we have inferred the dtypes correctly.
+  return g.GetAttr<size_t>("dtype_num_unknown_nodes") == 0;
+}
+
+inline bool DefaultSubgraphOpStorageType(const nnvm::NodeAttrs& attrs,
+                                         const int dev_mask,
+                                         DispatchMode* dispatch_mode,
+                                         std::vector<int>* in_stypes,
+                                         std::vector<int>* out_stypes) {
+  const nnvm::Symbol& subgraph_sym = nnvm::get<nnvm::Symbol>(attrs.parsed);
+  nnvm::Graph g;
+  g.outputs = subgraph_sym.outputs;
+  const auto& idx_g = g.indexed_graph();
+  CHECK_EQ(idx_g.input_nodes().size(), in_stypes->size());
+  CHECK_EQ(idx_g.outputs().size(), out_stypes->size());
+  exec::DevMaskVector dev_masks(idx_g.num_node_entries(), dev_mask);
+
+  // Put the input and output storages to the storage vector.
+  StorageTypeVector stypes(idx_g.num_node_entries(), kUndefinedStorage);
+  const auto &input_nids = idx_g.input_nodes();
+  CHECK_EQ(input_nids.size(), in_stypes->size());
+  for (size_t i = 0; i < in_stypes->size(); i++) {
+    auto eid = idx_g.entry_id(input_nids[i], 0);
+    stypes[eid] = in_stypes->at(i);
+  }
+  CHECK_EQ(g.outputs.size(), out_stypes->size());
+  for (size_t i = 0; i < out_stypes->size(); i++) {
+    auto eid = idx_g.entry_id(g.outputs[i]);
+    stypes[eid] = out_stypes->at(i);
+  }
+
+  // Infer storage type of the graph.
+  bool dev_match = g.attrs.count("dev_mask") &&
+                   g.GetAttr<exec::DevMaskVector>("dev_mask") == dev_masks;
+  if (!dev_match) {
+    g.attrs["dev_mask"] = std::make_shared<dmlc::any>(std::move(dev_masks));
+  }
+  g.attrs["storage_type"] = std::make_shared<dmlc::any>(std::move(stypes));
+  g = exec::InferStorageType(std::move(g));
+
+  stypes = g.GetAttr<StorageTypeVector>("storage_type");
+  // assign to in_types
+  for (size_t i = 0; i < in_stypes->size(); ++i) {
+    const auto eid = idx_g.entry_id(input_nids[i], 0);
+    STORAGE_TYPE_ASSIGN_CHECK(*in_stypes, i, stypes[eid]);
+  }
+
+  DISPATCH_MODE_ASSIGN_CHECK(dispatch_mode, 0, DispatchMode::kFComputeEx);
+  // assign to out_types
+  for (size_t i = 0; i < g.outputs.size(); ++i) {
+    const auto eid = idx_g.entry_id(g.outputs[i]);
+    STORAGE_TYPE_ASSIGN_CHECK(*out_stypes, i, stypes[eid]);
+  }
+  // Check if we have inferred the storages correctly.
+  return g.GetAttr<size_t>("storage_type_num_unknown_nodes") == 0;
+}
+
+inline ExecType DefaultSubgraphOpExecType(const nnvm::NodeAttrs& attrs) {
+  return ExecType::kSubgraphExec;
+}
+
+inline std::vector<uint32_t> DefaultSubgraphOpMutableInputs(const nnvm::NodeAttrs& attrs) {
+  const nnvm::Symbol& subgraph_sym = nnvm::get<nnvm::Symbol>(attrs.parsed);
+  const std::vector<std::string> input_names = subgraph_sym.ListInputNames(nnvm::Symbol::kAll);
+  const std::vector<std::string> immutable_input_names =
+    subgraph_sym.ListInputNames(nnvm::Symbol::kReadOnlyArgs);
+  const std::vector<std::string> mutable_input_names =
+    subgraph_sym.ListInputNames(nnvm::Symbol::kAuxiliaryStates);
+  CHECK_EQ(immutable_input_names.size() + mutable_input_names.size(), input_names.size());
+  std::vector<uint32_t> ret;
+  size_t i1 = 0, i2 = 0;
+  for (size_t i = 0; i < input_names.size(); ++i) {
+    if (i1 < immutable_input_names.size() && input_names[i] == immutable_input_names[i1]) {
+      ++i1;
+    } else {
+      CHECK(i2 < mutable_input_names.size());
+      CHECK_EQ(input_names[i], mutable_input_names[i2]);
+      ++i2;
+      ret.push_back(i);
+    }
+  }
+  return ret;
+}
+
+inline std::vector<ResourceRequest> DefaultSubgraphOpResourceRequest(const nnvm::NodeAttrs& attrs) {
+  const nnvm::Symbol& subgraph_sym = nnvm::get<nnvm::Symbol>(attrs.parsed);
+  static auto& fresource = Op::GetAttr<FResourceRequest>("FResourceRequest");
+  std::set<ResourceRequest::Type> resource_types;
+  DFSVisit(subgraph_sym.outputs, [&](const nnvm::NodePtr& node) {
+    if (!node->is_variable() && fresource.count(node->op())) {
+      for (ResourceRequest& r : fresource[node->op()](node->attrs)){
+        resource_types.insert(r.type);
+      }
+    }
+  });
+  return std::vector<ResourceRequest>(resource_types.begin(), resource_types.end());
+}
+
+#if 0
+// TODO(junwu): add this attribute for visible outputs
+inline uint32_t DefaultSubgraphOpNumVisibleOutputs(const nnvm::NodeAttrs& attrs) {
+}
+#endif
+
+}  // namespace op
+}  // namespace mxnet
+
+#endif  // MXNET_OPERATOR_SUBGRAPH_COMMON_H_
diff --git a/src/operator/subgraph/default_subgraph_op.cc b/src/operator/subgraph/default_subgraph_op.cc
new file mode 100644
index 0000000..8372ae9
--- /dev/null
+++ b/src/operator/subgraph/default_subgraph_op.cc
@@ -0,0 +1,113 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*   http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied.  See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+#include <mxnet/ndarray.h>
+#include "./default_subgraph_op.h"
+#include "../../imperative/imperative_utils.h"
+#include "../../imperative/cached_op.h"
+
+namespace mxnet {
+namespace op {
+
+#define SUBGRAPH_DEBUG 1
+
+class DefaultSubgraphOperator {
+ public:
+  explicit DefaultSubgraphOperator(const Symbol& sym) : subgraph_sym_(sym) {
+    subgraph_exec_.reset(new CachedOp(sym, {{"static_alloc", "true"}}));
+  }
+
+  void Forward(const OpContext& ctx,
+               const std::vector<NDArray>& inputs,
+               const std::vector<OpReqType>& req,
+               const std::vector<NDArray>& outputs);
+  void Backward(const OpContext& ctx,
+                const std::vector<NDArray>& inputs,
+                const std::vector<OpReqType>& req,
+                const std::vector<NDArray>& outputs) {
+    LOG(FATAL) << "Not implemented";
+  }
+
+ private:
+  nnvm::Symbol subgraph_sym_;
+  CachedOpPtr subgraph_exec_;
+};
+
+void DefaultSubgraphOperator::Forward(const OpContext& ctx,
+                                      const std::vector<NDArray>& inputs,
+                                      const std::vector<OpReqType>& req,
+                                      const std::vector<NDArray>& outputs) {
+  std::vector<NDArray> tmp_inputs = inputs;
+  std::vector<NDArray*> input_ptrs;
+  input_ptrs.reserve(inputs.size());
+  for (auto& nd : tmp_inputs) {
+    input_ptrs.push_back(&nd);
+  }
+  std::vector<NDArray> tmp_outputs = outputs;
+  std::vector<NDArray*> output_ptrs;
+  for (auto& nd : tmp_outputs) {
+    output_ptrs.push_back(&nd);
+  }
+#if SUBGRAPH_DEBUG
+  for (size_t i = 0; i < inputs.size(); ++i) {
+    LOG(INFO) << "inputs[" << i << "].version = " << inputs[i].version();
+  }
+  for (size_t i = 0; i < outputs.size(); ++i) {
+    LOG(INFO) << "outputs[" << i << "].version = " << outputs[i].version();
+  }
+#endif
+  subgraph_exec_->Forward(subgraph_exec_, input_ptrs, output_ptrs);
+}
+
+OpStatePtr CreateDefaultSubgraphOpState(const NodeAttrs& attrs,
+                                        Context ctx,
+                                        const std::vector<TShape>& in_shapes,
+                                        const std::vector<int>& in_types) {
+  const Symbol& subgraph_sym = nnvm::get<Symbol>(attrs.parsed);
+  return OpStatePtr::Create<DefaultSubgraphOperator>(subgraph_sym);
+}
+
+void DefaultSubgraphOpForward(const OpStatePtr& state_ptr,
+                              const OpContext& ctx,
+                              const std::vector<NDArray>& inputs,
+                              const std::vector<OpReqType>& req,
+                              const std::vector<NDArray>& outputs) {
+  DefaultSubgraphOperator& op = state_ptr.get_state<DefaultSubgraphOperator>();
+  op.Forward(ctx, inputs, req, outputs);
+}
+
+NNVM_REGISTER_OP(_default_subgraph_op)
+.describe(R"code(_default_subgraph_op)code" ADD_FILELINE)
+.set_num_inputs(DefaultSubgraphOpNumInputs)
+.set_num_outputs(DefaultSubgraphOpNumOutputs)
+.set_attr<nnvm::FListInputNames>("FListInputNames", DefaultSubgraphOpListInputs)
+.set_attr<nnvm::FListOutputNames>("FListOutputNames", DefaultSubgraphOpListOutputs)
+.set_attr<FCreateOpState>("FCreateOpState", CreateDefaultSubgraphOpState)
+.set_attr<nnvm::FInferShape>("FInferShape", DefaultSubgraphOpShape)
+.set_attr<nnvm::FInferType>("FInferType", DefaultSubgraphOpType)
+.set_attr<FInferStorageType>("FInferStorageType", DefaultSubgraphOpStorageType)
+.set_attr<FStatefulComputeEx>("FStatefulComputeEx<cpu>", DefaultSubgraphOpForward)
+.set_attr<nnvm::FMutateInputs>("FMutateInputs", DefaultSubgraphOpMutableInputs)
+.set_attr<FResourceRequest>("FResourceRequest", DefaultSubgraphOpResourceRequest)
+.set_attr<std::string>("key_var_num_args", "num_args")
+.set_attr<FExecType>("FExecType", DefaultSubgraphOpExecType)
+.add_argument("data", "NDArray-or-Symbol[]", "input data list");
+
+}  // namespace op
+}  // namespace mxnet
diff --git a/src/operator/subgraph/default_subgraph_op.cu b/src/operator/subgraph/default_subgraph_op.cu
new file mode 100644
index 0000000..15a76e3
--- /dev/null
+++ b/src/operator/subgraph/default_subgraph_op.cu
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*!
+ *  Copyright (c) 2018 by Contributors
+ * \file subgraph_op.cu
+ * \brief GPU Implementation of subgraph operations
+ */
+
+#include "./default_subgraph_op.h"
+
+namespace mxnet {
+namespace op {
+
+void DefaultSubgraphOpForward(const OpStatePtr& state_ptr,
+                              const OpContext& ctx,
+                              const std::vector<NDArray>& inputs,
+                              const std::vector<OpReqType>& req,
+                              const std::vector<NDArray>& outputs);
+
+NNVM_REGISTER_OP(_default_subgraph_op)
+.set_attr<FStatefulComputeEx>("FStatefulComputeEx<gpu>", DefaultSubgraphOpForward);
+
+}  // namespace op
+}  // namespace mxnet
diff --git a/src/operator/subgraph/default_subgraph_op.h b/src/operator/subgraph/default_subgraph_op.h
new file mode 100644
index 0000000..7d6624e
--- /dev/null
+++ b/src/operator/subgraph/default_subgraph_op.h
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef MXNET_OPERATOR_SUBGRAPH_DEFAULT_SUBGRAPH_OP_H_
+#define MXNET_OPERATOR_SUBGRAPH_DEFAULT_SUBGRAPH_OP_H_
+
+#include <vector>
+#include <string>
+#include "./common.h"
+
+namespace mxnet {
+namespace op {
+
+/*
+ * This provides criteria for selecting nodes in a subgraph.
+ * When a node is passed to this object, the selection criteria may be changed.
+ * We can also specify what links we should use when traversing the neighbor
+ * nodes.
+ */
+class SubgraphSelector {
+ public:
+  virtual ~SubgraphSelector() {
+  }
+  // Determine if the node should be selected for a subgraph.
+  virtual bool Select(const nnvm::Node &n) = 0;
+  // Determine if the input node should be selected for a subgraph.
+  virtual bool SelectInput(const nnvm::Node &n, const nnvm::Node &new_node) = 0;
+  // Determine if the output node should be selected for a subgraph.
+  virtual bool SelectOutput(const nnvm::Node &n, const nnvm::Node &new_node) = 0;
+  // Post processes pre-selected subgraph nodes. Return a list of nodes that
+  // users want to keep in subgraph(s).
+  virtual std::vector<nnvm::Node*> Filter(nnvm::Graph* g,
+                                          const std::vector<nnvm::Node*>& candidates) {
+    return candidates;
+  }
+};
+
+using SubgraphSelectorPtr = std::shared_ptr<SubgraphSelector>;
+
+/*!
+ * \brief This provides a set of properties for partitioning a graph into subgraphs,
+ * reconstructing a new graph from the subgraphs and creating a subgraph
+ * operator to execute the subgraph.
+ */
+class SubgraphProperty {
+ public:
+  // the criteria of selecting the subgraph nodes.
+  virtual SubgraphSelectorPtr CreateSubgraphSelector() const = 0;
+  // create an nnvm node for a given subgraph. Here users can customize how to
+  // execute the operators in the subgraph.
+  virtual nnvm::NodePtr CreateSubgraphNode(const nnvm::Symbol &s,
+                                           const int subgraph_id = 0) const = 0;
+};
+
+using SubgraphPropertyPtr = std::shared_ptr<SubgraphProperty>;
+
+void RegisterSubgraphProperty(SubgraphPropertyPtr property);
+
+/*
+ * This selects nodes for a subgraph that only contains operators
+ * in a given set and it visits nodes via both input and output links.
+ */
+class ContainOpSelector: public SubgraphSelector {
+  std::shared_ptr<const std::unordered_set<std::string>> op_names;
+
+ public:
+  explicit ContainOpSelector(std::shared_ptr<const std::unordered_set<std::string>> op_names) {
+    this->op_names = op_names;
+  }
+
+  virtual bool Select(const nnvm::Node &n) {
+    return !n.is_variable() && op_names->count(n.op()->name);
+  }
+
+  virtual bool SelectInput(const nnvm::Node &n, const nnvm::Node &new_node) {
+    return !new_node.is_variable() && op_names->count(new_node.op()->name);
+  }
+
+  virtual bool SelectOutput(const nnvm::Node &n, const nnvm::Node &new_node) {
+    return !new_node.is_variable() && op_names->count(new_node.op()->name);
+  }
+};
+
+/*
+ * This subgraph property finds a subgraph whose nodes have only operators
+ * within a set. The operators in the subgraph will be executed by _default_subgraph_op.
+ */
+class DefaultSubgraphProperty: public SubgraphProperty {
+ public:
+  explicit DefaultSubgraphProperty(const std::unordered_set<std::string> &op_names) :
+    op_names_(std::make_shared<std::unordered_set<std::string>>(op_names)) {}
+  virtual nnvm::NodePtr CreateSubgraphNode(const nnvm::Symbol &sym,
+                                           const int subgraph_id = 0) const {
+    nnvm::NodePtr n = nnvm::Node::Create();
+    n->attrs.op = Op::Get("_default_subgraph_op");
+    n->attrs.name = "_default_subgraph_op" + std::to_string(subgraph_id);
+    n->attrs.parsed = sym;
+    return n;
+  }
+  virtual SubgraphSelectorPtr CreateSubgraphSelector() const {
+    return std::make_shared<ContainOpSelector>(op_names_);
+  }
+
+ private:
+  std::shared_ptr<const std::unordered_set<std::string>> op_names_;
+};
+
+}  // namespace op
+}  // namespace mxnet
+
+#endif  // MXNET_OPERATOR_SUBGRAPH_DEFAULT_SUBGRAPH_OP_H_
diff --git a/src/operator/subgraph/partition_graph.cc b/src/operator/subgraph/partition_graph.cc
new file mode 100644
index 0000000..11af49a
--- /dev/null
+++ b/src/operator/subgraph/partition_graph.cc
@@ -0,0 +1,687 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*!
+ *  Copyright (c) 2018 by Contributors
+ * \file partition_graph.cc
+ * \brief
+ */
+#include <nnvm/graph.h>
+#include <nnvm/pass.h>
+#include <mxnet/op_attr_types.h>
+#include <unordered_set>
+#include <stack>
+#include <queue>
+
+#include "./default_subgraph_op.h"
+#include "./common.h"
+
+namespace nnvm {
+NodePtr CreateVariableNode(const std::string& name);
+}
+
+namespace mxnet {
+
+namespace op {
+
+using nnvm::Symbol;
+using nnvm::Node;
+using nnvm::NodePtr;
+using nnvm::NodeEntry;
+using nnvm::Graph;
+
+// TODO(junwu): Change this to 0
+#define SUBGRAPH_DEBUG 1
+
+namespace sg {  // sg stands for subgraph
+
+#if SUBGRAPH_DEBUG
+void PrintSubgraph(const std::vector<SimpleNode*>& simple_nodes) {
+  std::string op_names = "";
+  for (size_t i = 0; i < simple_nodes.size(); ++i) {
+    op_names += simple_nodes[i]->node->attrs.name + ' ';
+  }
+  LOG(INFO) << "Subgraph node names: " << op_names;
+}
+
+void PrintNodeEntry(const nnvm::NodeEntry& entry) {
+  std::string ret = "NodeEntry: node_name=" + entry.node->attrs.name
+    + ", index=" + std::to_string(entry.index) + ", version=" + std::to_string(entry.version);
+  LOG(INFO) << ret;
+}
+
+void PrintNodeEntries(const std::vector<nnvm::NodeEntry*>& entries) {
+  for (size_t i = 0; i < entries.size(); ++i) {
+    PrintNodeEntry(*entries[i]);
+  }
+}
+#endif
+
+/*!
+ * \brief Given a MXNet computational graph, create an undirected graph from it.
+ * \param g the MXNet computational graph
+ * \param simple_nodes the nodes of undirected graph in top sorted order
+ */
+void CreateSimpleGraph(const Graph& g,
+                       std::vector<SimpleNodePtr>* simple_nodes) {
+  const auto& indexed_graph = g.indexed_graph();
+  simple_nodes->reserve(indexed_graph.num_nodes());
+  DFSVisit(g.outputs, [&](const NodePtr& node) {
+    SimpleNodePtr sn = SimpleNode::Create();
+    sn->node = node.get();
+    for (size_t i = 0; i < sn->node->inputs.size(); ++i) {
+      const auto& e = sn->node->inputs[i];
+      const auto input_nid = indexed_graph.node_id(e.node.get());
+      CHECK_LT(input_nid, simple_nodes->size());
+      auto& input_node_outputs = (*simple_nodes)[input_nid]->outputs;
+      auto it = input_node_outputs.find(sn->node);
+      if (it == input_node_outputs.end()) {
+        input_node_outputs.emplace(sn->node, std::vector<size_t>{i});
+      } else {
+        it->second.push_back(i);
+      }
+    }
+    simple_nodes->emplace_back(std::move(sn));
+  });
+}
+
+/*!
+ * \brief Reset labels of the subgraph nodes to the original state
+ * and clear the vector of subgraph nodes.
+ */
+void ResetNodeLabels(const nnvm::Graph& g,
+                     const std::vector<SimpleNodePtr>& simple_nodes,
+                     std::vector<nnvm::Node*>* subgraph_nodes) {
+  for (auto n : *subgraph_nodes) {
+    const auto nid = g.indexed_graph().node_id(n);
+    simple_nodes[nid]->label = -1;
+  }
+  subgraph_nodes->clear();
+}
+
+/*!
+ * \brief This function traverses the nodes in a computation graph from a starting
+ * node following the input edges and output edges, and marks all nodes that
+ * can be accessed from the starting node. Before the function returns,
+ * it will conduct checking whether there is a loop between the potential subgraph
+ * and the outside nodes. If so, add the node that should break the loop
+ * in excluded_nodes and return false. Otherwise, return true.
+ * \param g the whole graph
+ * \subgraph_selector determines whether the visited node should be choosen or not
+ * \label the label of the current subgraph
+ * \snid node id of the seed simple node
+ * \simple_nodes all simple nodes in the top sorted order
+ * \subgraph_nodes all the nodes belonging to the same subgraph of seed node
+ * \excluded_nodes set of nodes that should be excluded from the current subgraph
+ */
+bool LabelSubgraph(const Graph& g,
+                   SubgraphSelectorPtr subgraph_selector,
+                   const int label,
+                   const size_t snid,  // simple node id, this is a seed
+                   const std::vector<SimpleNodePtr>& simple_nodes,
+                   std::vector<nnvm::Node*>* subgraph_nodes,
+                   std::unordered_set<const nnvm::Node*>* excluded_nodes = nullptr) {
+  const auto& indexed_graph = g.indexed_graph();
+  std::queue<SimpleNode*> node_queue;
+  if (!excluded_nodes || !excluded_nodes->count(simple_nodes[snid]->node)) {
+    CHECK_EQ(simple_nodes[snid]->label, -1);
+    simple_nodes[snid]->label = label;
+    node_queue.push(simple_nodes[snid].get());
+  }
+  // key: nodes that serve as input/output nodes to the subgraph
+  // value: pair of vectors of nodes in the subgraph. The first vector contains the
+  // output nodes of the key in the subgraph, and the second vector contains the
+  // input ndoes of the key in the subgraph. If both vectors are non-empty,
+  // it means there is a loop between the subgraph and the key node.
+  // When breaking the loop, we want to start removing the node with the largest node id.
+  std::unordered_map<const nnvm::Node*,
+    std::pair<std::vector<const nnvm::Node*>,
+              std::vector<const nnvm::Node*>>> non_subgraph_node_map;
+  while (!node_queue.empty()) {
+    SimpleNode* cur_node = node_queue.front();
+    node_queue.pop();
+    subgraph_nodes->push_back(cur_node->node);
+    // get qualified adjacent input nodes
+    for (auto& e : cur_node->node->inputs) {
+      const bool select_input = (!excluded_nodes || !excluded_nodes->count(e.node.get()))
+        && subgraph_selector->SelectInput(*cur_node->node, *e.node);
+      if (select_input) {
+        // e.node is a subgraph node
+        const auto nid = indexed_graph.node_id(e.node.get());
+        CHECK_LT(nid, simple_nodes.size());
+        // this node has not been visited yet
+        if (simple_nodes[nid]->label == -1) {
+          simple_nodes[nid]->label = label;
+          node_queue.push(simple_nodes[nid].get());
+        }
+      } else {
+        // e.node is an input node of the subgraph
+        non_subgraph_node_map[e.node.get()].first.push_back(cur_node->node);
+      }
+    }
+    // get qualified output nodes
+    for (auto it = cur_node->outputs.begin(); it != cur_node->outputs.end(); ++it) {
+      const bool select_output = (!excluded_nodes || !excluded_nodes->count(it->first))
+          && subgraph_selector->SelectOutput(*cur_node->node, *it->first);
+      if (select_output) {
+        // it->first is a subgraph node
+        const auto nid = indexed_graph.node_id(it->first);
+        CHECK_LT(nid, simple_nodes.size());
+        // this node has not been visited yet
+        if (simple_nodes[nid]->label == -1) {
+          simple_nodes[nid]->label = label;
+          node_queue.push(simple_nodes[nid].get());
+        }
+      } else {
+        // it->first is an output node of the subgraph
+        non_subgraph_node_map[it->first].second.push_back(cur_node->node);
+      }
+    }
+  }
+  auto node_cmp = [&] (const nnvm::Node* node1, const nnvm::Node* node2) {
+    return indexed_graph.node_id(node1) < indexed_graph.node_id(node2);
+  };
+  // check whether there is a loop between the subgraph and its input/output nodes
+  int excluded_node_id = -1;
+  for (auto& kv : non_subgraph_node_map) {
+    auto& output_nodes = kv.second.first;
+    auto& input_nodes = kv.second.second;
+    if (!output_nodes.empty() && !input_nodes.empty()) {
+      // there is a loop between kv->first and the subgraph
+      std::sort(output_nodes.begin(), output_nodes.end(), node_cmp);
+      std::sort(input_nodes.begin(), input_nodes.end(), node_cmp);
+      const auto node_id = std::max(indexed_graph.node_id(output_nodes.back()),
+                                    indexed_graph.node_id(input_nodes.back()));
+      excluded_node_id = std::max(excluded_node_id, static_cast<int>(node_id));
+    }
+  }
+  if (excluded_node_id != -1) {
+    CHECK_LT(excluded_node_id, static_cast<int>(simple_nodes.size()));
+    CHECK_NE(excluded_node_id, static_cast<int>(snid))
+      << "A cycle is found in the computational graph between nodes "
+      << simple_nodes[excluded_node_id]->node->attrs.name << " and "
+      << simple_nodes[snid]->node->attrs.name;
+    excluded_nodes->insert(simple_nodes[excluded_node_id]->node);
+    ResetNodeLabels(g, simple_nodes, subgraph_nodes);
+    return false;
+  }
+  std::sort(subgraph_nodes->begin(), subgraph_nodes->end(), node_cmp);
+  return true;
+}
+
+/*!
+ * \brief Finds all the nodes belonging to the same subgraph given a seed node.
+ * \param g the whole graph
+ * \subgraph_selector determines whether the visited node should be choosen or not
+ * \label the label of the current subgraph
+ * \snid node id of the seed simple node
+ * \simple_nodes all simple nodes in the top sorted order
+ * \subgraph_nodes all the nodes belonging to the same subgraph of seed node
+ * \return Subgraph node candidates sorted in the topological order
+ */
+void PreSelectSubgraphNodes(const Graph& g,
+                            SubgraphSelectorPtr subgraph_selector,
+                            const int label,
+                            const size_t snid,
+                            const std::vector<SimpleNodePtr>& simple_nodes,
+                            std::vector<nnvm::Node*>* subgraph_nodes) {
+  std::unordered_set<const nnvm::Node*> excluded_nodes;
+  const size_t max_num_retry = simple_nodes.size() * simple_nodes.size();
+  size_t count = 0;
+  bool success = false;
+  while (!success && count < max_num_retry) {
+    success = LabelSubgraph(g, subgraph_selector, label, snid, simple_nodes,
+                            subgraph_nodes, &excluded_nodes);
+    if (!success) {
+      CHECK(!excluded_nodes.empty());
+      std::string excluded_node_names;
+      for (auto node : excluded_nodes) {
+        excluded_node_names += node->attrs.name + ", ";
+      }
+      LOG(INFO) << "Found a cycle when BFS from node " << simple_nodes[snid]->node->attrs.name
+                << ". Excluding nodes " << excluded_node_names << "and retrying";
+    }
+    ++count;
+  }
+  if (!success) {
+    LOG(INFO) << "Tried " << count << " times of finding subgraphs starting from node "
+              << simple_nodes[snid]->node->attrs.name << " without success because a loop "
+                  "is always found between the subgraph and some other nodes. Will treat "
+                  "seed node " << simple_nodes[snid]->node->attrs.name
+              << "as a subgraph with one node";
+    CHECK(subgraph_nodes->empty());
+    simple_nodes[snid]->label = label;
+    subgraph_nodes->push_back(simple_nodes[snid]->node);
+  }
+}
+
+/*!
+ * \brief Given a vector of nodes, group them into individual subgraphs
+ * based upon their connectivity.
+ */
+void PostProcessNodeCandidates(const nnvm::Graph& g,
+                               const std::vector<nnvm::Node*>& nodes,
+                               const std::vector<SimpleNodePtr>& simple_nodes,
+                               std::vector<std::vector<SimpleNode*>>* subgraphs,
+                               size_t* subgraph_id) {
+  const auto& indexed_graph = g.indexed_graph();
+  std::unordered_set<nnvm::Node*> node_set(nodes.begin(), nodes.end());
+  auto simple_node_cmp = [&] (const SimpleNode* node1, const SimpleNode* node2) {
+    return indexed_graph.node_id(node1->node) < indexed_graph.node_id(node2->node);
+  };
+  for (auto node : nodes) {
+    if (!node_set.count(node)) {
+      // The node has been included in a subgraph
+      continue;
+    }
+    std::queue<nnvm::Node*> q;
+    q.push(node);
+    CHECK_EQ(node_set.erase(node), 1U);
+    subgraphs->emplace_back();
+    const auto nid = indexed_graph.node_id(node);
+    simple_nodes[nid]->label = *subgraph_id;
+    subgraphs->back().push_back(simple_nodes[nid].get());
+    while (!q.empty()) {
+      nnvm::Node* cur_node = q.front();
+      q.pop();
+      for (auto& e : cur_node->inputs) {
+        auto in_it = node_set.find(e.node.get());
+        if (in_it != node_set.end()) {
+          q.push(*in_it);
+          const auto in_nid = indexed_graph.node_id(*in_it);
+          simple_nodes[in_nid]->label = *subgraph_id;
+          subgraphs->back().push_back(simple_nodes[in_nid].get());
+          node_set.erase(in_it);
+        }
+      }
+      const auto cur_nid = indexed_graph.node_id(cur_node);
+      const SimpleNode* cur_snode = simple_nodes[cur_nid].get();
+      for (const auto& kv : cur_snode->outputs) {
+        const auto out_it = node_set.find(kv.first);
+        if (out_it != node_set.end()) {
+          q.push(*out_it);
+          const auto out_nid = indexed_graph.node_id(*out_it);
+          simple_nodes[out_nid]->label = *subgraph_id;
+          subgraphs->back().push_back(simple_nodes[out_nid].get());
+          node_set.erase(out_it);
+        }
+      }
+    }
+    ++(*subgraph_id);
+    std::sort(subgraphs->back().begin(), subgraphs->back().end(), simple_node_cmp);
+  }
+  CHECK(node_set.empty());
+}
+
+/*!
+ * \brief Finds subgraphs with all nodes that meet certain criteria.
+ * All nodes in a subgraph are marked with the same label.
+ */
+void FindSubgraphs(Graph* g,
+                   const SubgraphProperty &subg_prop,
+                   const std::vector<SimpleNodePtr>& simple_nodes,
+                   std::vector<std::vector<SimpleNode*>>* subgraph_nodes) {
+  const auto& indexed_graph = g->indexed_graph();
+  CHECK_EQ(indexed_graph.num_nodes(), simple_nodes.size());
+  auto node_cmp = [&] (const nnvm::Node* node1, const nnvm::Node* node2) {
+    return indexed_graph.node_id(node1) < indexed_graph.node_id(node2);
+  };
+  size_t subgraph_id = 0;
+  for (size_t i = 0; i < simple_nodes.size(); ++i) {
+    nnvm::Node* node = simple_nodes[i]->node;
+    auto subgraph_selector = subg_prop.CreateSubgraphSelector();
+    if (subgraph_selector->Select(*node) && simple_nodes[i]->label == -1) {
+      // pre-select nodes that can be grouped in a subgraph
+      std::vector<nnvm::Node*> preselected_nodes;
+      PreSelectSubgraphNodes(*g, subgraph_selector, subgraph_id, i, simple_nodes,
+                             &preselected_nodes);
+
+      // filter out unqualified pre-selected nodes
+      std::vector<nnvm::Node*> filtered_nodes = subgraph_selector->Filter(g, preselected_nodes);
+
+      // make sure filtered_nodes is a subset of preselected_nodes
+      for (const auto n : filtered_nodes) {
+        const auto nit = std::find(preselected_nodes.begin(), preselected_nodes.end(), n);
+        CHECK(nit != preselected_nodes.end())
+          << "Node " << n->attrs.name << " is not found in the pre-selected subgraph nodes."
+             " Please make sure that no new nodes were added in your subgraph"
+             " selector's Filter function";
+      }
+
+      // make sure nodes are sorted
+      std::sort(filtered_nodes.begin(), filtered_nodes.end(), node_cmp);
+
+      // reset node labels that are not in filtered nodes
+      for (const auto n : preselected_nodes) {
+        const auto nit = std::find(filtered_nodes.begin(), filtered_nodes.end(), n);
+        if (nit == filtered_nodes.end()) {
+          simple_nodes[indexed_graph.node_id(n)]->label = -1;
+        }
+      }
+      // find out subgraphs from the filtered nodes
+      std::vector<std::vector<SimpleNode*>> subgraphs;
+      PostProcessNodeCandidates(*g, filtered_nodes, simple_nodes, &subgraphs, &subgraph_id);
+      if (!subgraphs.empty()) {
+        subgraph_nodes->insert(subgraph_nodes->end(), subgraphs.begin(), subgraphs.end());
+      }
+    }
+  }
+}
+
+/*!
+ * \brief Sorts entries according to their topological order.
+ * Note that entry ids cannot be used to sort entries.
+ * \param entry_top_order_map mapping from entry pointer to its topological position in the graph
+ * \param entries Node entries to be sorted
+ */
+void SortEntries(const std::unordered_map<const nnvm::NodeEntry*, size_t>& entry_top_order_map,
+                 std::vector<nnvm::NodeEntry*>* entries) {
+  auto entry_cmp = [&](const nnvm::NodeEntry* e1, const nnvm::NodeEntry* e2) {
+    const auto it1 = entry_top_order_map.find(e1);
+    CHECK(it1 != entry_top_order_map.end());
+    const auto it2 = entry_top_order_map.find(e2);
+    CHECK(it2 != entry_top_order_map.end());
+    return it1->second < it2->second;
+  };
+  std::sort(entries->begin(), entries->end(), entry_cmp);
+}
+
+/*!
+ * \brief Given a subgraph, find the output entries of a subgraph.
+ * \param g pointer to the whole graph
+ * \param simple_nods vector of simple nodes in top sorted order
+ * \param subgraph_nodes vector of pointers of simples of a subgraph.
+ * \param entry_top_order_map mapping entry pointer to its top sorted position
+ * \param input_entries input entries of the subgraph
+ */
+
+void FindInputEntries(const Graph& g,
+                      const std::vector<SimpleNodePtr>& simple_nodes,
+                      const std::vector<SimpleNode*>& subgraph_nodes,
+                      const std::unordered_map<const nnvm::NodeEntry*, size_t>& entry_top_order_map,
+                      std::vector<nnvm::NodeEntry*>* input_entries) {
+  const auto& indexed_graph = g.indexed_graph();
+  int label = -1;
+  for (size_t i = 0; i < subgraph_nodes.size(); ++i) {
+    if (label == -1) {
+      label = subgraph_nodes[i]->label;
+    } else {
+      CHECK_EQ(subgraph_nodes[i]->label, label);
+    }
+    auto& inputs = subgraph_nodes[i]->node->inputs;
+    for (size_t j = 0; j < inputs.size(); ++j) {
+      auto& e = inputs[j];
+      if (indexed_graph.exist(e.node.get())) {
+        // e's source node is not a subgraph node
+        const auto nid = indexed_graph.node_id(e.node.get());
+        // this is a node not belonging to the subgraph
+        if (simple_nodes[nid]->label != label) {
+          input_entries->push_back(&e);
+        }
+      } else {
+        // e's source node is a subgraph node.
+        // In this case, two subgraphs are adjacent.
+        input_entries->push_back(&e);
+      }
+    }
+  }
+  SortEntries(entry_top_order_map, input_entries);
+}
+
+/*!
+ * \brief Given a subgraph, find the output entries of a subgraph.
+ * \param g pointer to the whole graph
+ * \param simple_nods vector of simple nodes in top sorted order
+ * \param subgraph_nodes vector of pointers of simples of a subgraph.
+ * \param entry_top_order_map mapping entry pointer to its top sorted position
+ * \param output_entries output entries of the subgraph
+ */
+void FindOutputEntries(Graph* g,
+                       const std::vector<SimpleNodePtr>& simple_nodes,
+                       const std::vector<SimpleNode*>& subgraph_nodes,
+                       const std::unordered_map<const nnvm::NodeEntry*, size_t>&
+                         entry_top_order_map,
+                       std::vector<nnvm::NodeEntry*>* output_entries) {
+  if (subgraph_nodes.empty()) return;
+  const auto& indexed_graph = g->indexed_graph();
+  int label = -1;
+  for (size_t i = 0; i < subgraph_nodes.size(); ++i) {
+    if (label == -1) {
+      label = subgraph_nodes[i]->label;
+    } else {
+      CHECK_EQ(subgraph_nodes[i]->label, label);
+    }
+    for (auto it = subgraph_nodes[i]->outputs.begin();
+         it != subgraph_nodes[i]->outputs.end(); ++it) {
+      if (indexed_graph.exist(it->first)) {
+        // if the output node is a normal graph node (not a subgraph node)
+        const auto nid = indexed_graph.node_id(it->first);
+        // this is a node not belonging to the current subgraph
+        if (simple_nodes[nid]->label != label) {
+          // TODO(zhengda) I need to test this.
+          for (auto idx : it->second) {
+            auto& e = simple_nodes[nid]->node->inputs[idx];
+            output_entries->push_back(&e);
+          }
+        }
+      } else {
+        // if the output node is a subgraph node
+        // two graphs are adjacent
+        for (auto idx : it->second) {
+          output_entries->push_back(&(it->first->inputs[idx]));
+        }
+      }
+    }
+  }
+  // Check if current subgraph contains a node which is the last node
+  // of the whole graph. If so, save its corresponding entry as well.
+  for (size_t i = 0; i < g->outputs.size(); ++i) {
+    auto& entry = g->outputs[i];
+    // The entry might has been updated as an output of
+    // a subgraph node. In this case, no need
+    // to check its source for the current subgraph. Otherwise,
+    // do the following.
+    if (indexed_graph.exist(entry.node.get())) {
+      const auto nid = indexed_graph.node_id(entry.node.get());
+      if (simple_nodes[nid]->label == label) {
+        output_entries->push_back(&entry);
+      }
+    }
+  }
+  SortEntries(entry_top_order_map, output_entries);
+}
+
+/*!
+ * \brief Given a computation graph and a set of input node entries, this function cuts
+ * the node entries and creates new variable nodes as the input nodes of the
+ * subgraph. It returns the nodes that connect to the subgraph directly and
+ * the names of the new variable nodes.
+ */
+void CutGraphInputs(const std::vector<nnvm::NodeEntry*> &input_entries,
+                    std::vector<nnvm::NodeEntry> *orig_entries,
+                    const bool skip_var = false) {
+  orig_entries->resize(input_entries.size());
+  for (size_t i = 0; i < input_entries.size(); ++i) {
+    nnvm::NodeEntry *e = input_entries[i];
+    // If the node is a variable itself, we may want to skip the node.
+    if (e->node->is_variable() && skip_var) {
+      continue;
+    }
+
+    orig_entries->at(i) = *e;
+    nnvm::Symbol sym;
+    sym.outputs.push_back(*e);
+    const auto output_names = sym.ListOutputNames();
+    CHECK_EQ(output_names.size(), 1U);
+    nnvm::NodePtr n = nnvm::CreateVariableNode(output_names[0]);
+    *e = nnvm::NodeEntry{n, 0, 0};
+  }
+}
+
+/*!
+ * \brief Replace a set of nodes belonging to the same subgraph with a subgrpah node
+ * and keep the subgraph in the subgraph node. The input entries and output entries
+ * of the subgraph node are kept in the same order as the subgraph's.
+ */
+void CreateSubgraphNode(Graph* g,
+                        const std::vector<SimpleNodePtr>& simple_nodes,
+                        const std::vector<SimpleNode*>& subgraph_nodes,
+                        const size_t subgraph_id,
+                        std::unordered_map<const nnvm::NodeEntry*, size_t>* entry_top_order_map) {
+#if SUBGRAPH_DEBUG
+  LOG(INFO) << "Searching for input entries...";
+#endif
+  std::vector<nnvm::NodeEntry*> input_entries;
+  FindInputEntries(*g, simple_nodes, subgraph_nodes, *entry_top_order_map, &input_entries);
+  std::vector<nnvm::NodeEntry> orig_input_entries;
+  // TODO(junwu): Confirm what value to pass to skip_var
+  CutGraphInputs(input_entries, &orig_input_entries, false);
+#if SUBGRAPH_DEBUG
+  PrintNodeEntries(input_entries);
+  LOG(INFO) << "Searching for output entries...";
+#endif
+  std::vector<nnvm::NodeEntry*> output_entries;
+  FindOutputEntries(g, simple_nodes, subgraph_nodes, *entry_top_order_map, &output_entries);
+
+  // Create a subgraph for the subgraph node
+  nnvm::Symbol sym;
+  sym.outputs.resize(output_entries.size());
+  for (size_t i = 0; i < output_entries.size(); ++i) {
+    sym.outputs[i] = *output_entries[i];
+  }
+  const SubgraphPropertyPtr& subg_prop = g->GetAttr<SubgraphPropertyPtr>("subgraph_property");
+  nnvm::NodePtr n = subg_prop->CreateSubgraphNode(sym, subgraph_id);
+
+  // Connect the external nodes to the subgraph node.
+  for (size_t i = 0; i < output_entries.size(); ++i) {
+    *output_entries[i] = nnvm::NodeEntry{n, static_cast<uint32_t>(i), 0};
+  }
+  n->inputs = orig_input_entries;
+  const auto& indexed_graph = g->indexed_graph();
+  for (size_t i = 0; i < n->inputs.size(); ++i) {
+    auto& e = n->inputs[i];
+    // update entry_top_order_map with newly created orig_input_entries
+    auto it = entry_top_order_map->find(input_entries[i]);
+    CHECK(it != entry_top_order_map->end());
+    CHECK_EQ(entry_top_order_map->count(&e), 0U);
+    entry_top_order_map->emplace(&e, it->second);
+    // update input entries' source simple nodes' outputs map
+    nnvm::Node* node = e.node.get();
+    if (indexed_graph.exist(node)) {
+      const auto nid = indexed_graph.node_id(node);
+      SimpleNode* sn = simple_nodes[nid].get();
+      for (SimpleNode* dest_node : subgraph_nodes) {
+        sn->outputs.erase(dest_node->node);
+      }
+      sn->outputs[n.get()].push_back(i);
+    }
+  }
+#if SUBGRAPH_DEBUG
+  PrintNodeEntries(output_entries);
+#endif
+}
+
+}  // namespace sg
+
+/*!
+ * \brief Sort entries of all the nodes' inputs vectors in the topological order.
+ * This is going to be used to sort input/output entries of subgraphs to keep
+ * the topological order unchanged.
+ */
+void TopSortEntries(const Graph& g,
+                    std::unordered_map<const nnvm::NodeEntry*, size_t>* entry_top_order_map) {
+  CHECK(entry_top_order_map != nullptr);
+  std::unordered_set<const nnvm::Node*> visited;
+  // tuple: (graph node, index of node's inputs, node entry as the output of the graph node)
+  std::stack<std::tuple<nnvm::Node*, size_t, const nnvm::NodeEntry*>> s;
+  auto in_degree = [] (const nnvm::Node* node)->size_t {
+    if (!node) {
+      return 0;
+    }
+    CHECK_EQ(node->control_deps.size(), 0U);
+    return node->inputs.size();
+  };
+  for (auto& e : g.outputs) {
+    nnvm::Node* node = e.node.get();
+    if (visited.count(node) == 0U) {
+      s.emplace(node, 0U, &e);
+      visited.insert(node);
+    }
+    while (!s.empty()) {
+      auto& top = s.top();
+      if (std::get<1>(top) == in_degree(std::get<0>(top))) {
+        // The node's inputs has been exhausted.
+        entry_top_order_map->emplace(std::get<2>(top), entry_top_order_map->size());
+        s.pop();
+      } else {
+        // The node still has input entries not visited.
+        CHECK_LT(std::get<1>(top), std::get<0>(top)->inputs.size());
+        auto& entry = std::get<0>(top)->inputs[std::get<1>(top)++];
+        nnvm::Node* input_node = entry.node.get();
+        if (visited.count(input_node) == 0U) {
+          // The entry's source node has not been visited.
+          // Push the entry to the stack for marking order later.
+          s.emplace(input_node, 0U, &entry);
+          visited.insert(input_node);
+        } else {
+          // The entry's source node has been visited before.
+          // Marking order for it.
+          entry_top_order_map->emplace(&entry, entry_top_order_map->size());
+        }
+      }
+    }
+  }
+}
+
+Graph PartitionGraph(Graph&& g) {
+  if (!g.HasAttr("subgraph_property")) {  // treat the whole graph as a subgraph
+    LOG(INFO) << "The graph has no attribute of subgraph_property attached. "
+                 "The original graph is returned.";
+    return g;
+  }
+  using namespace sg;
+  const SubgraphPropertyPtr& subg_prop = g.GetAttr<SubgraphPropertyPtr>("subgraph_property");
+  // top sort NodeEntry of all the nodes' inputs
+  std::unordered_map<const nnvm::NodeEntry*, size_t> entry_top_order_map;
+  TopSortEntries(g, &entry_top_order_map);
+
+  // Create undirected graph for ease of finding subgraphs
+  std::vector<SimpleNodePtr> simple_nodes;
+  CreateSimpleGraph(g, &simple_nodes);
+  std::vector<std::vector<SimpleNode*>> subgraph_nodes;
+  FindSubgraphs(&g, *subg_prop, simple_nodes, &subgraph_nodes);
+  for (size_t i = 0; i < subgraph_nodes.size(); ++i) {
+#if SUBGRAPH_DEBUG
+    std::set<SimpleNode*> simple_node_set(subgraph_nodes[i].begin(), subgraph_nodes[i].end());
+    CHECK_EQ(simple_node_set.size(), subgraph_nodes[i].size());
+    PrintSubgraph(subgraph_nodes[i]);
+#endif
+    CreateSubgraphNode(&g, simple_nodes, subgraph_nodes[i], i, &entry_top_order_map);
+  }
+  return g;
+}
+
+NNVM_REGISTER_PASS(PartitionGraph)
+.describe("Partition a graph according to the user defined rules "
+          "in a derived class of SubgraphProperty")
+.set_body(PartitionGraph)
+.set_change_graph(true);
+
+}  // namespace op
+}  // namespace mxnet
diff --git a/tests/python/gpu/test_operator_gpu.py b/tests/python/gpu/test_operator_gpu.py
index a3e663a..f5b260f 100644
--- a/tests/python/gpu/test_operator_gpu.py
+++ b/tests/python/gpu/test_operator_gpu.py
@@ -44,6 +44,7 @@ from test_gluon_rnn import *
 from test_sparse_ndarray import *
 from test_sparse_operator import *
 from test_ndarray import *
+from test_subgraph_op import *
 
 set_default_context(mx.gpu(0))
 del test_support_vector_machine_l1_svm  # noqa
diff --git a/tests/python/unittest/test_gluon_trainer.py b/tests/python/unittest/test_gluon_trainer.py
index 2a34400..13e8e4e 100644
--- a/tests/python/unittest/test_gluon_trainer.py
+++ b/tests/python/unittest/test_gluon_trainer.py
@@ -175,6 +175,7 @@ def test_trainer_save_load():
     # check if parameter dict is correctly associated with optimizer after load_state
     assert trainer._kvstore._updater.optimizer._get_lr(0) == 0.2
 
+@unittest.skip("temporarily disabled till it gets fixed. tracked at https://github.com/apache/incubator-mxnet/issues/11353")
 @with_seed()
 def test_trainer_reset_kv():
     def check_trainer_reset_kv(kv):
diff --git a/tests/python/unittest/test_subgraph_op.py b/tests/python/unittest/test_subgraph_op.py
new file mode 100644
index 0000000..f08c42c
--- /dev/null
+++ b/tests/python/unittest/test_subgraph_op.py
@@ -0,0 +1,135 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+import ctypes
+import mxnet as mx
+from mxnet.base import SymbolHandle, check_call, _LIB, mx_uint, c_str_array
+from mxnet.symbol import Symbol
+import numpy as np
+
+
+def test_subgraph():
+    def get_graph():
+        data1 = mx.sym.Variable('data1', shape=(3, 3, 10, 10), dtype=np.float32)
+        data2 = mx.sym.Variable('data2', shape=(1, 0, 2, 2))
+        data3 = mx.sym.sin(data2)
+        conv = mx.sym.Convolution(data=data1, weight=data3, kernel=(2, 2), num_filter=1)
+        rets = []
+        rets.append((conv, []))
+        rets.append((conv, [mx.sym.sin.__name__]))
+        rets.append((conv, [mx.sym.Convolution.__name__]))
+        rets.append((conv, [mx.sym.sin.__name__, mx.sym.Convolution.__name__]))
+        return rets
+
+    for regular_sym, op_names in get_graph():
+        input_names = regular_sym.list_inputs()
+        shapes = regular_sym.infer_shape()
+        types = regular_sym.infer_type()
+        out = SymbolHandle()
+
+        check_call(_LIB.MXPartitionGraph(regular_sym.handle, mx_uint(len(op_names)),
+            c_str_array(op_names), ctypes.byref(out)))
+        subgraph_sym = Symbol(out)
+        assert input_names == subgraph_sym.list_inputs()
+
+        print(subgraph_sym.list_outputs())
+        assert shapes == subgraph_sym.infer_shape()
+        assert types == subgraph_sym.infer_type()
+
+        regular_exec = regular_sym.simple_bind(ctx=mx.cpu(), grad_req='null')
+        subgraph_exec = subgraph_sym.simple_bind(ctx=mx.cpu(), grad_req='null')
+
+        for name in input_names:
+            regular_exec.arg_dict[name][:] = mx.nd.random.normal(
+                    shape=regular_exec.arg_dict[name].shape)
+            subgraph_exec.arg_dict[name][:] = regular_exec.arg_dict[name]
+
+        subgraph_exec.forward()
+        regular_exec.forward()
+        mx.nd.waitall()
+        assert (subgraph_exec.outputs[0] - regular_exec.outputs[0]).abs().sum().asscalar() == 0.0
+
+
+def test_input_name_order():
+    def check_input_order(sym, op_names):
+        out = SymbolHandle()
+        check_call(_LIB.MXPartitionGraph(sym.handle, mx_uint(len(op_names)),
+                                         c_str_array(op_names), ctypes.byref(out)))
+
+        new_sym = Symbol(out)
+        #print(sym.list_inputs())
+        #print(new_sym.list_inputs())
+        assert new_sym.list_inputs() == sym.list_inputs()
+        assert new_sym.list_arguments() == sym.list_arguments()
+        assert new_sym.list_auxiliary_states() == sym.list_auxiliary_states()
+        #print(new_sym.list_arguments())
+        #print(new_sym.list_auxiliary_states())
+        #print('original outputs: %s' % sym.list_outputs())
+        #print('new sym outputs: %s' % new_sym.list_outputs())
+
+    def test_network_structure_1():
+        data1 = mx.sym.var('data1')
+        data2 = mx.sym.var('data2')
+        conv1 = mx.sym.Convolution(data=data1, weight=data2, no_bias=True, kernel=(2, 2), num_filter=1)
+        conv2 = mx.sym.Convolution(data=data2, weight=data1, no_bias=True, kernel=(2, 2), num_filter=1)
+        out = mx.sym.Group([conv1, conv2])
+        check_input_order(out, ['Convolution'])
+
+    def test_network_structure_2():
+        data1 = mx.sym.var('data1')
+        data2 = mx.sym.var('data2')
+        conv1 = mx.sym.Convolution(data=data1, weight=data2, no_bias=True, kernel=(2, 2), num_filter=1)
+        conv2 = mx.sym.Convolution(data=data2, weight=data1, no_bias=True, kernel=(2, 2), num_filter=1)
+        out = conv1 + conv2
+        check_input_order(out, ['Convolution'])
+        check_input_order(out, ['Convolution', '_Plus', 'elemwise_add', '_plus'])
+
+    def test_network_structure_3():
+        # this tests whether the partitioning algorithm can deal with cycles
+        data = mx.sym.var('data')
+        ret = mx.sym.exp(data)
+        ret1 = mx.sym.cos(ret)
+        ret2 = mx.sym.sin(ret)
+        ret = ret1 + ret2
+        check_input_order(ret, ['exp', 'sin', '_Plus', 'elemwise_add', '_plus'])
+        check_input_order(ret, ['exp', 'cos', '_Plus', 'elemwise_add', '_plus'])
+
+    def test_network_structure_4():
+        # this tests whether the partitioned sym can distinguish in_args and aux_states
+        data = mx.sym.var('data')
+        ret = mx.sym.exp(data)
+        ret1 = mx.sym.cos(ret)
+        ret2 = mx.sym.sin(ret)
+        ret = ret1 + ret2
+        ret = mx.sym.BatchNorm(ret)
+        ret = mx.sym.BatchNorm(ret)
+        check_input_order(ret, ['exp', 'sin', '_Plus', 'elemwise_add', '_plus'])
+        check_input_order(ret, ['exp', 'cos', '_Plus', 'elemwise_add', '_plus'])
+        check_input_order(ret, ['exp', 'sin', '_Plus', 'elemwise_add', '_plus', 'BatchNorm'])
+        check_input_order(ret, ['exp', 'cos', '_Plus', 'elemwise_add', '_plus', 'BatchNorm'])
+        check_input_order(ret, ['exp', 'BatchNorm'])
+        check_input_order(ret, ['BatchNorm'])
+
+    test_network_structure_1()
+    test_network_structure_2()
+    test_network_structure_3()
+    test_network_structure_4()
+
+
+if __name__ == '__main__':
+    import nose
+    nose.runmodule()