Skip to content

Commit bb0e6e4

Browse files
committed
Update the developer guide and fill it with links to the source code
1 parent 6a46aab commit bb0e6e4

File tree

1 file changed

+169
-53
lines changed

1 file changed

+169
-53
lines changed

docs/developer-guide.md

Lines changed: 169 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,8 @@ To dig into the code, you probably want to start by getting
2222
it building and the tests running on your system. While you can
2323
work with just the pure C++ DyND library, we recommend you get
2424
the Python bindings and build and run both simultaneously. The
25-
instructions to get the source code and build it is available
26-
in the document
27-
28-
https://github.com/libdynd/dynd-python/blob/master/BUILD_INSTALL.md
25+
instructions to get the source code and build it is available in the
26+
[build/install guide for dynd-python](https://github.com/libdynd/dynd-python/blob/master/BUILD_INSTALL.md).
2927

3028
Running The Tests
3129
-----------------
@@ -37,7 +35,7 @@ and Linux.
3735

3836
The C++ tests are using the google test framework, and to
3937
run them you simply run the program 'test_dynd' which is built
40-
from the dynd/tests subdirectory. On Windows MSVC, right
38+
from the libdynd/tests subdirectory. On Windows MSVC, right
4139
click on the test_dynd project and choose "Set as StartUp
4240
Project", so when you hit play, the tests will run.
4341

@@ -46,6 +44,32 @@ tests can be run with a command like
4644

4745
python -c "import dynd;dynd.test()"
4846

47+
Background Introductory Material
48+
--------------------------------
49+
50+
To get some insight into some of the design choices made in DyND,
51+
there are some introductory slides created in
52+
[Jupyter notebook](http://ipython.org/notebook.html) form, and
53+
presentable using the
54+
[Live Reveal](https://github.com/damianavila/live_reveal)
55+
Jupyter extension.
56+
57+
The first set of such slides is about
58+
[how DyND views memory](http://nbviewer.ipython.org/github/libdynd/libdynd/blob/master/docs/intro-01/HowDyNDViewsMemory.ipynb).
59+
60+
Three video talks about DyND are available. One was presented at the
61+
[AMS in January 2013](https://ams.confex.com/ams/93Annual/webprogram/Paper224314.html),
62+
another was presented at
63+
[SciPy in June 2013](https://conference.scipy.org/scipy2013/presentation_detail.php?id=175), and the third was presented as a lightning talk at
64+
[EuroSciPy in August 2014](https://www.euroscipy.org/2014/schedule/euroscipy-2014-general-sessions/).
65+
DyND was also mentioned in a Blaze talk at
66+
[SciPy in July 2014](https://conference.scipy.org/scipy2014/schedule/presentation/1717/).
67+
68+
* [AMS January 2013 DyND Talk](https://ams.confex.com/ams/93Annual/flvgateway.cgi/id/23375?recordingid=23375)
69+
* [SciPy June 2013 DyND Talk](https://www.youtube.com/watch?v=BduIKN5mgvU)
70+
* [SciPy July 2014 Blaze Talk](https://www.youtube.com/watch?v=9HPR-1PdZUk)
71+
* [EuroSciPy August 2014 DyND Lightning Talk](https://www.youtube.com/watch?v=VZ7enVMNB84#t=198)
72+
4973
Source Code Directory Layout
5074
----------------------------
5175

@@ -63,42 +87,121 @@ to ``include/*``.
6387

6488
### Main Source
6589

66-
In the ``include/dynd`` directory, the files implementing the
67-
main DyND objects are ``type.hpp`` and ``array.hpp``.
68-
The file ``config.hpp`` has some per-compiler logic to
69-
enable/disable various C++11 features, define some common
70-
macros, and declare the version number strings.
90+
In the
91+
[``include/dynd``](https://github.com/libdynd/libdynd/tree/master/include/dynd)
92+
directory, the files implementing the main DyND objects are
93+
[``type.hpp``](https://github.com/libdynd/libdynd/blob/master/include/dynd/type.hpp)
94+
and
95+
[``array.hpp``](https://github.com/libdynd/libdynd/blob/master/include/dynd/array.hpp).
96+
The file
97+
[``config.hpp``](https://github.com/libdynd/libdynd/blob/master/include/dynd/config.hpp)
98+
has some per-compiler logic to enable/disable various supported
99+
C++ features, define some common macros, and declare the
100+
version number strings.
71101

72102
### Types Source
73103

74104
All the DyND types are presently located in
75-
``include/dynd/types``. The file ``include/type.hpp``
76-
basically contain a smart pointer which wraps instances
77-
of type ``base_dtype *`` in a more convenient interface.
78-
The file ``include/dtypes/type_id.hpp`` contains a number
79-
of primitive enumeration types and some type_id metaprograms.
105+
[``include/dynd/types``](https://github.com/libdynd/libdynd/tree/master/include/dynd/types).
106+
The file
107+
[``include/dynd/type.hpp``](https://github.com/libdynd/libdynd/blob/master/include/dynd/type.hpp)
108+
basically contain a smart pointer which wraps instances of type
109+
[``base_type *``](https://github.com/libdynd/libdynd/blob/master/include/dynd/types/base_type.hpp)
110+
in a more convenient interface. The file
111+
[``include/dtypes/type_id.hpp``](https://github.com/libdynd/libdynd/blob/master/include/dynd/types/type_id.hpp)
112+
contains a number of primitive enumeration types and some
113+
type_id metaprograms.
80114

81115
There are a number of ``base_<kind>_dtype`` dtype classes
82116
which correspond to a number of the dtype 'kinds'. For
83-
example, if a dtype is of ``dim`` kind, then it
84-
must inherit from ``base_dim_dtype``.
117+
example, if a dtype is of the ``dim`` kind, then it must inherit from
118+
[``base_dim_type``](https://github.com/libdynd/libdynd/blob/master/include/dynd/types/base_dim_type.hpp).
85119

86120
The code which consumes and produces Blaze datashapes is in
87-
``include/dtypes/datashape_parser.hpp`` and
88-
``include/dtypes/datashape_formatter.hpp``.
121+
[``include/dynd/types/datashape_parser.hpp``](https://github.com/libdynd/libdynd/blob/master/include/dynd/types/datashape_parser.hpp)
122+
and
123+
[``include/dynd/types/datashape_formatter.hpp``](https://github.com/libdynd/libdynd/blob/master/include/dynd/types/datashape_formatter.hpp).
124+
125+
See [the DataShape documentation](http://datashape.pydata.org/)
126+
for more general information about datashape.
127+
128+
### Arrays Source
129+
130+
The DyND
131+
[``nd::array``](https://github.com/libdynd/libdynd/blob/master/include/dynd/array.hpp)
132+
object is a smart-pointer object which wraps the lower-level types, memory
133+
blocks, and arrmeta handling into an object with a more convenient
134+
interface. This object has reference semantics, copying one ``nd::array``
135+
to another creates another reference to the same object. It also has
136+
many constructors from C++ objects, which create new ``nd::array``
137+
objects of the appropriate type, with a copy of the value provided.
138+
139+
Some example code creating and modifying an ``nd::array``:
140+
141+
```c++
142+
// Initialize an array using C++11 initializer list
143+
nd::array a = {1.5, 2.0, 3.1};
144+
cout << a << endl;
145+
// Assign one value
146+
a(1).vals() = 100;
147+
cout << a << endl;
148+
// Assign a range (slightly more efficient with vals_at)
149+
a.vals_at(irange() < 2) = {9, 10};
150+
cout << a << endl;
151+
```
152+
153+
Output:
154+
155+
```
156+
array([1.5, 2, 3.1],
157+
type="3 * float64")
158+
array([1.5, 100, 3.1],
159+
type="3 * float64")
160+
array([ 9, 10, 3.1],
161+
type="3 * float64")
162+
```
89163
90-
See https://github.com/libdynd/datashape/tree/master/docs/source
91-
for more general information aboud datashape.
92-
93-
### Kernels Source
164+
### Func Source
94165
95-
Kernels in DyND are mostly implemented in the
96-
``include/kernels`` directory. All kernels get built in
97-
the ``ckernel_builder`` class, which is defined in
98-
``include/kernels/ckernel_builder.hpp``. These kernels
99-
are intended to be cheap to construct and execute when they
100-
are small, but scale to hold acceleration structures and other
101-
information when what they are computing is more complex.
166+
The
167+
[``func``](https://github.com/libdynd/libdynd/tree/master/include/dynd/func)
168+
namespace is where the
169+
[``nd::arrfunc``](https://github.com/libdynd/libdynd/blob/master/include/dynd/func/arrfunc.hpp)
170+
and
171+
[``nd::callable``](https://github.com/libdynd/libdynd/blob/master/include/dynd/func/callable.hpp)
172+
objects are defined, which provide
173+
array function abstractions. The ``nd::arrfunc`` is being actively
174+
developed, and the plan is for ``callable`` to go away once all its
175+
functionality can be superceded.
176+
177+
From C++, the easiest way to create an arrfunc is with
178+
[``make_apply_arrfunc``](https://github.com/libdynd/libdynd/blob/master/include/dynd/func/apply_arrfunc.hpp),
179+
which uses template metaprogramming to automatically generate the
180+
required dynamic type information, ckernels, and glue functions that
181+
an ``nd::arrfunc`` requires.
182+
183+
Another useful operation, after you've created a scalar arrfunc, is
184+
to lift the arrfunc into something like a NumPy ufunc with
185+
[``lift_arrfunc``](https://github.com/libdynd/libdynd/blob/master/include/dynd/func/lift_arrfunc.hpp).
186+
Another example that has a more interesting function signature is
187+
[``make_rolling_arrfunc``](https://github.com/libdynd/libdynd/blob/master/include/dynd/func/rolling_arrfunc.hpp),
188+
which applies a provided arrfunc to every interval of an array in
189+
a rolling fashion.
190+
191+
### CKernels Source
192+
193+
Before an ``nd::arrfunc`` is executed, it first gets lowered into
194+
a ckernel. This low level abstraction defines an array-oriented,
195+
possibly hierarchical way to combine code and data.
196+
197+
CKernels in DyND are mostly implemented in the
198+
[``include/kernels``](https://github.com/libdynd/libdynd/tree/master/include/dynd/kernels)
199+
directory. All kernels get built via the
200+
[``ckernel_builder``](https://github.com/libdynd/libdynd/blob/master/include/dynd/kernels/ckernel_builder.hpp)
201+
class. These kernels are intended to be cheap to construct and
202+
execute when they are small, but scale to hold acceleration
203+
structures and other information when what they are computing
204+
is more complex.
102205
103206
An example trivial case is a kernel which adds two floating
104207
point numbers, which as a ckernel will consist of just the
@@ -115,7 +218,9 @@ for the component functions of the expression.
115218
116219
There are presently three kinds of kernels that are defined
117220
and used within DyND: ``expr_single_t``, ``expr_strided_t``,
118-
and ``expr_predicate_t``. In all three cases there is an
221+
and ``expr_predicate_t``, defined in
222+
[ckernel_prefix.hpp](https://github.com/libdynd/libdynd/blob/master/include/dynd/kernels/ckernel_prefix.hpp).
223+
In all three cases there is an
119224
array of ``src`` inputs, and a single ``dst`` output, which
120225
is a boolean value returned in an ``int`` for the predicate
121226
case.
@@ -147,29 +252,44 @@ performed.
147252
Unary kernels, where the number of ``src`` inputs is one,
148253
form the backbone of being able to copy values between
149254
types. Some basic utilities for defining and working
150-
with them are in ``include/kernels/assignment_kernels.hpp``.
255+
with them are in
256+
[``assignment_kernels.hpp``](https://github.com/libdynd/libdynd/blob/master/include/dynd/kernels/assignment_kernels.hpp).
257+
258+
General-purpose helper classes for defining ckernels are in
259+
[``ckernel_builder.hpp``](https://github.com/libdynd/libdynd/blob/master/include/dynd/kernels/ckernel_builder.hpp),
260+
implemented to work for both regular CPU and CUDA via some
261+
preprocessor code.
151262
152263
### Memory Blocks Source
153264
154-
Dynamic nd::array data in DyND is stored in memory blocks,
155-
which are in the ``include/memblock`` directory. The base
156-
class is defined in ``include/memblock/memory_block.hpp``,
265+
Dynamic ``nd::array`` data in DyND is stored in memory blocks,
266+
which are in the
267+
[``dynd/memblock``](https://github.com/libdynd/libdynd/tree/master/include/dynd/memblock)
268+
directory. The base class is defined in
269+
[``memory_block.hpp``](https://github.com/libdynd/libdynd/blob/master/include/dynd/memblock/memory_block.hpp),
157270
and the different memory blocks serve the needs of
158271
various dtypes.
159272
160-
The ``array_memory_block`` is for nd::array instances. The file
161-
``include/array.hpp`` defines an object which contains an
162-
array_memory_block and defines operations on it. In typical
273+
The
274+
[``array_memory_block``](https://github.com/libdynd/libdynd/blob/master/include/dynd/memblock/array_memory_block.hpp)
275+
is for nd::array instances. The file
276+
[``dynd/array.hpp``](https://github.com/libdynd/libdynd/blob/master/include/dynd/array.hpp)
277+
defines an object which contains an ``array_memory_block`` and
278+
defines operations on it. In typical
163279
usage, this contains the type, arrmeta, and a reference+pointer
164280
to memory holding the data. As an optimization, it is possible
165281
to allocate an ``array_memory_block`` with extra memory at
166282
the end to store the data with fewer memory allocations, in
167283
which case the reference to the data contains NULL.
168284
169-
The ``fixed_size_pod_memory_block`` is very simple, for data
170-
types that have a fixed size and alignment.
285+
The
286+
[``fixed_size_pod_memory_block``](https://github.com/libdynd/libdynd/blob/master/include/dynd/memblock/fixed_size_pod_memory_block.hpp)
287+
is very simple, for POD (plain old data) types that have a fixed
288+
size and alignment.
171289
172-
The ``pod_memory_block`` provides a simple memory
290+
The
291+
[``pod_memory_block``](https://github.com/libdynd/libdynd/blob/master/include/dynd/memblock/pod_memory_block.hpp)
292+
provides a simple pooled memory
173293
allocator that doles out chunks of memory sequentially
174294
for variable-sized data types. Due to the way nd::array
175295
uses views, similar to NumPy, once some memory has been
@@ -178,20 +298,16 @@ deallocated until the whole memory block is freed.
178298
A small exception is for reusable temporary buffers, and a
179299
``reset`` operation is provided to support that use case.
180300
181-
The ``zeroinit_memory_block`` is just like pod_memory_block,
182-
but initializes the memory it allocates to zero before
183-
returning it. Types have a flag indicating whether they
184-
require zero-initialization or not.
301+
The
302+
[``zeroinit_memory_block``](https://github.com/libdynd/libdynd/blob/master/include/dynd/memblock/zeroinit_memory_block.hpp)
303+
is just like pod_memory_block, but initializes the memory it
304+
allocates to zero before returning it. Types have a flag
305+
indicating whether they require zero-initialization or not.
185306
186-
The ``external_memory_block`` is for holding on to data owned
307+
The
308+
[``external_memory_block``](https://github.com/libdynd/libdynd/blob/master/include/dynd/memblock/external_memory_block.hpp)
309+
is for holding on to data owned
187310
by a system external to DyND. For example, in some cases
188311
DyND can directly map onto the string data of Python's
189312
immutable strings, by using this type of memory block
190313
and flagging the nd::array as immutable.
191-
192-
### Func Source
193-
194-
The ``func`` namespace is where the ``nd::arrfunc`` and
195-
``nd::callable`` objects are defined, which provide
196-
array function abstractions. These have gone through much
197-
evolution, and are still a work in progress.

0 commit comments

Comments
 (0)