You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

282 lines
11 KiB

  1. Sylvan
  2. =====================
  3. Sylvan is a parallel (multi-core) MTBDD library written in C. Sylvan
  4. implements parallelized operations on BDDs, MTBDDs and LDDs. Both
  5. sequential and parallel BDD-based algorithms can benefit from
  6. parallelism. Sylvan uses the work-stealing framework Lace and parallel
  7. datastructures to implement scalable multi-core operations on decision
  8. diagrams.
  9. Sylvan is developed (© 2011-2016) by the `Formal Methods and
  10. Tools <http://fmt.ewi.utwente.nl/>`__ group at the University of Twente
  11. as part of the MaDriD project, which is funded by NWO, and (© 2016-2017)
  12. by the `Formal Methods and Verification <http://fmv.jku.at/>`__ group at
  13. the Johannes Kepler University Linz as part of the RiSE project. Sylvan
  14. is licensed with the Apache 2.0 license.
  15. The main author of the project is Tom van Dijk who can be reached via
  16. tom@tvandijk.nl.
  17. Please let us know if you use Sylvan in your projects and if you need
  18. decision diagram operations that are currently not implemented in Sylvan.
  19. The main repository of Sylvan is https://github.com/trolando/sylvan. A
  20. mirror is available at https://github.com/utwente-fmt/sylvan.
  21. Bindings for other languages than C/C++ also exist:
  22. - Java/JNI bindings: https://github.com/utwente-fmt/jsylvan
  23. - Haskell bindings: https://github.com/adamwalker/sylvan-haskell
  24. - Python bindings: https://github.com/johnyf/dd
  25. Dependencies
  26. ------------
  27. Sylvan has the following required dependencies:
  28. - **CMake** for compiling.
  29. - **gmp** (``libgmp-dev``) for the GMP leaves in MTBDDs.
  30. - **hwloc** (``libhwloc-dev``) for pinning worker threads to processors.
  31. Sylvan depends on the `work-stealing framework
  32. Lace <http://fmt.ewi.utwente.nl/tools/lace>`__ for its implementation.
  33. Lace is embedded in the Sylvan distribution.
  34. Building
  35. --------
  36. It is recommended to build Sylvan in a separate build directory:
  37. .. code:: bash
  38. mkdir build
  39. cd build
  40. cmake ..
  41. make && make test && make install
  42. It is recommended to use ``ccmake`` to configure the build settings of Sylvan. For example,
  43. you can choose whether you want shared/static libraries, whether you want to enable
  44. statistics gathering and whether you want a ``Debug`` or a ``Release`` build.
  45. Using Sylvan
  46. ------------
  47. To use Sylvan, the library and its dependency Lace must be initialized:
  48. .. code:: c
  49. #include <sylvan.h>
  50. main() {
  51. int n_workers = 0; // auto-detect
  52. lace_init(n_workers, 0);
  53. lace_startup(0, NULL, NULL);
  54. size_t nodes_minsize = 1LL<<22;
  55. size_t nodes_maxsize = 1LL<<26;
  56. size_t cache_minsize = 1LL<<23;
  57. size_t cache_maxsize = 1LL<<27;
  58. sylvan_init_package(nodes_minsize, nodes_maxsize, cache_minsize, cache_maxsize);
  59. sylvan_init_mtbdd();
  60. ...
  61. sylvan_stats_report(stdout);
  62. sylvan_quit();
  63. lace_exit();
  64. }
  65. The call to ``lace_init`` initializes the Lace framework, which sets up the data structures
  66. for work-stealing. The parameter ``n_workers`` can be set to 0 for auto-detection. The
  67. function ``lace_startup`` then creates all other worker threads. The worker threads run
  68. until ``lace_exit`` is called. Lace must be started before Sylvan can be initialized.
  69. Sylvan is initialized with a call to ``sylvan_init_package``. Here we choose the initial
  70. and maximum sizes of the nodes table and the operation cache. In the example, we choose a maximum
  71. nodes table size of 2^26 and a maximum cache size of 2^27. The initial sizes are
  72. set to 2^22 and 2^23, respectively. The sizes must be powers of 2.
  73. Sylvan allocates memory for the maximum sizes *in virtual memory* but only uses the space
  74. needed for the initial sizes. The sizes are doubled during garbage collection, until the maximum
  75. size has been reached.
  76. After ``sylvan_init_package``, the subpackages ``mtbdd`` and ``ldd`` can be initialized with
  77. ``sylvan_init_mtbdd`` and ``sylvan_init_ldd``. This mainly allocates auxiliary datastructures for
  78. garbage collection.
  79. If you enable statistics generation (via CMake) then you can use ``sylvan_stats_report`` to report
  80. the obtained statistics to a given ``FILE*``.
  81. The Lace framework
  82. ~~~~~~~~~~~~~~~~~~
  83. Sylvan uses the Lace framework to offer 'automatic' parallelization of decision diagram operations.
  84. Many functions in Sylvan are Lace tasks. To call a Lace task, the variables
  85. ``__lace_worker`` and ``__lace_dq_head`` must be initialized **locally**.
  86. Use the macro ``LACE_ME`` to initialize the variables in every function that calls Sylvan functions
  87. and is not itself a Lace task.
  88. Garbage collection and referencing nodes
  89. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  90. Like all decision diagram implementations, Sylvan performs garbage collection.
  91. Garbage collection is triggered when trying to insert a new node and no
  92. empty space can be found in the table within a reasonable upper bound.
  93. To ensure that no decision diagram nodes are overwritten, you must ensure that
  94. Sylvan knows which decision diagrams you care about.
  95. The easiest way to do this is with ``sylvan_protect`` and ``sylvan_unprotect`` to protect
  96. a given pointer.
  97. These functions protect the decision diagram referenced to by that pointer at the time
  98. that garbage collection is performed.
  99. Unlike some other implementations of decision diagrams,
  100. you can modify the variable between the calls to ``sylvan_protect`` and ``sylvan_unprotect``
  101. without explicitly changing the reference.
  102. To manually trigger garbage collection, call ``sylvan_gc``.
  103. You can use ``sylvan_gc_disable`` and ``sylvan_gc_enable`` to disable garbage collection or
  104. enable it again. If garbage collection is disabled, the program will abort when the nodes table
  105. is full.
  106. **Warning**: Sylvan is a multi-threaded library and all workers must cooperate for garbage collection. If you use locking mechanisms in your code, beware of deadlocks!
  107. Basic BDD functionality
  108. ~~~~~~~~~~~~~~~~~~~~~~~
  109. To create new BDDs, you can use:
  110. - ``sylvan_true``: representation of constant ``true``.
  111. - ``sylvan_false``: representation of constant ``false``.
  112. - ``sylvan_ithvar(var)``: representation of literal <var> (negated: ``sylvan_nithvar(var)``)
  113. To follow the BDD edges and obtain the variable at the root of a BDD,
  114. you can use (only for internal nodes, not for leaves ``sylvan_true`` and ``sylvan_false``):
  115. - ``sylvan_var(bdd)``: obtain the variable of the root node of <bdd>.
  116. - ``sylvan_high(bdd)``: follow the high edge of <bdd>.
  117. - ``sylvan_low(bdd)``: follow the low edge of <bdd>.
  118. You need to manually reference BDDs that you want to keep during garbage
  119. collection:
  120. - ``sylvan_protect(bddptr)``: add a pointer reference to <bddptr>.
  121. - ``sylvan_unprotect(bddptr)``: remove a pointer reference to <bddptr>.
  122. - ``sylvan_ref(bdd)``: add a reference to <bdd>.
  123. - ``sylvan_deref(bdd)``: remove a reference to <bdd>.
  124. It is recommended to use ``sylvan_protect`` and ``sylvan_unprotect``.
  125. The C++ objects (defined in ``sylvan_obj.hpp``) handle this automatically.
  126. The following basic operations are implemented:
  127. - ``sylvan_not(bdd)``: compute the negation of <bdd>.
  128. - ``sylvan_ite(a,b,c)``: compute 'if <a> then <b> else <c>'.
  129. - ``sylvan_and(a, b)``: compute '<a> and <b>'
  130. - ``sylvan_or(a, b)``: compute '<a> or <b>'
  131. - ``sylvan_nand(a, b)``: compute 'not (<a> and <b>)'
  132. - ``sylvan_nor(a, b)``: compute 'not (<a> or <b>)'
  133. - ``sylvan_imp(a, b)``: compute '<a> then <b>'
  134. - ``sylvan_invimp(a, b)``: compute '<b> then <a>'
  135. - ``sylvan_xor(a, b)``: compute '<a> xor <b>'
  136. - ``sylvan_equiv(a, b)``: compute '<a> = <b>'
  137. - ``sylvan_diff(a, b)``: compute '<a> and not <b>'
  138. - ``sylvan_less(a, b)``: compute '<b> and not <a>'
  139. - ``sylvan_exists(bdd, vars)``: existential quantification of <bdd> with respect to variables <vars>.
  140. - ``sylvan_forall(bdd, vars)``: universal quantification of <bdd> with respect to variables <vars>.
  141. A set of variables (like <vars> above) is a BDD representing the conjunction of the variables.
  142. Other BDD operations
  143. ~~~~~~~~~~~~~~~~~~~~
  144. See ``src/sylvan_bdd.h`` for other operations on BDDs, especially operations
  145. that are relevant for model checking.
  146. Basic MTBDD functionality
  147. ~~~~~~~~~~~~~~~~~~~~~~~~~
  148. See ``src/sylvan_mtbdd.h`` for operations on multi-terminal BDDs.
  149. Basic LDD functionality
  150. ~~~~~~~~~~~~~~~~~~~~~~~
  151. See ``src/sylvan_ldd.h`` for operations on List DDs.
  152. Support for C++
  153. ~~~~~~~~~~~~~~~
  154. See ``src/sylvan_obj.hpp`` for the C++ interface.
  155. .. Adding custom decision diagram operations
  156. .. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  157. Table resizing
  158. ~~~~~~~~~~~~~~
  159. During garbage collection, it is possible to resize the nodes table and
  160. the cache. Sylvan provides two default implementations: an aggressive
  161. version that resizes every time garbage collection is performed, and a
  162. less aggressive version that only resizes when at least half the table is
  163. full. This can be configured in ``src/sylvan_config.h``. It is not
  164. possible to decrease the size of the nodes table and the cache.
  165. Dynamic reordering
  166. ~~~~~~~~~~~~~~~~~~
  167. Dynamic reordening is not yet supported. For now, we suggest users
  168. find a good static variable ordering.
  169. Examples
  170. --------
  171. Simple examples can be found in the ``examples`` subdirectory. The file
  172. ``simple.cpp`` contains a toy program that uses the C++ objects to
  173. perform basic BDD manipulation. The ``mc.c`` and ``lddmc.c`` programs
  174. are more advanced examples of symbolic model checking (with example
  175. models in the ``models`` subdirectory).
  176. Troubleshooting
  177. ---------------
  178. Sylvan may require a larger than normal program stack. You may need to
  179. increase the program stack size on your system using ``ulimit -s``.
  180. Segmentation faults on large computations typically indicate a program
  181. stack overflow.
  182. I am getting the error "unable to allocate memory: ...!"
  183. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  184. Sylvan allocates virtual memory using mmap. If you specify a combined
  185. size for the cache and node table larger than your actual available
  186. memory you may need to set ``vm.overcommit_memory`` to ``1``. E.g.
  187. ``echo 1 > /proc/sys/vm/overcommit_memory``. You can make this setting
  188. permanent with
  189. ``echo "vm.overcommit_memory = 1" > /etc/sysctl.d/99-sylvan.conf``. You
  190. can verify the setting with ``cat /proc/sys/vm/overcommit_memory``. It
  191. should report ``1``.
  192. I get errors about ``__lace_worker`` and ``__lace_dq_head``
  193. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  194. Many Sylvan operations are implemented as Lace tasks. To call a Lace
  195. task, the variables ``__lace_worker`` and ``__lace_dq_head`` must be
  196. initialized. Use the macro ``LACE_ME`` to do this. Only use ``LACE_ME``
  197. locally (in a function), never globally!
  198. Publications
  199. ------------
  200. T. van Dijk (2016) `Sylvan: Multi-core Decision
  201. Diagrams <http://dx.doi.org/10.3990/1.9789036541602>`__. PhD Thesis.
  202. T. van Dijk and J.C. van de Pol (2016) `Sylvan: Multi-core Framework
  203. for Decision Diagrams <http://dx.doi.org/10.1007/s10009-016-0433-2>`__.
  204. In: STTT (Special Issue), Springer.
  205. T. van Dijk and J.C. van de Pol (2015) `Sylvan: Multi-core Decision
  206. Diagrams <http://dx.doi.org/10.1007/978-3-662-46681-0_60>`__. In: TACAS
  207. 2015, LNCS 9035. Springer.
  208. T. van Dijk and A.W. Laarman and J.C. van de Pol (2012) `Multi-Core BDD
  209. Operations for Symbolic
  210. Reachability <http://eprints.eemcs.utwente.nl/22166/>`__. In: PDMC 2012,
  211. ENTCS. Elsevier.