@@ -22,10 +22,8 @@ To dig into the code, you probably want to start by getting
22
22
it building and the tests running on your system. While you can
23
23
work with just the pure C++ DyND library, we recommend you get
24
24
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 ) .
29
27
30
28
Running The Tests
31
29
-----------------
@@ -37,7 +35,7 @@ and Linux.
37
35
38
36
The C++ tests are using the google test framework, and to
39
37
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
41
39
click on the test_dynd project and choose "Set as StartUp
42
40
Project", so when you hit play, the tests will run.
43
41
@@ -46,6 +44,32 @@ tests can be run with a command like
46
44
47
45
python -c "import dynd;dynd.test()"
48
46
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
+
49
73
Source Code Directory Layout
50
74
----------------------------
51
75
@@ -63,42 +87,121 @@ to ``include/*``.
63
87
64
88
### Main Source
65
89
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.
71
101
72
102
### Types Source
73
103
74
104
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.
80
114
81
115
There are a number of `` base_<kind>_dtype `` dtype classes
82
116
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 ) .
85
119
86
120
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
+ ```
89
163
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
94
165
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.
102
205
103
206
An example trivial case is a kernel which adds two floating
104
207
point numbers, which as a ckernel will consist of just the
@@ -115,7 +218,9 @@ for the component functions of the expression.
115
218
116
219
There are presently three kinds of kernels that are defined
117
220
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
119
224
array of ``src`` inputs, and a single ``dst`` output, which
120
225
is a boolean value returned in an ``int`` for the predicate
121
226
case.
@@ -147,29 +252,44 @@ performed.
147
252
Unary kernels, where the number of ``src`` inputs is one,
148
253
form the backbone of being able to copy values between
149
254
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.
151
262
152
263
### Memory Blocks Source
153
264
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),
157
270
and the different memory blocks serve the needs of
158
271
various dtypes.
159
272
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
163
279
usage, this contains the type, arrmeta, and a reference+pointer
164
280
to memory holding the data. As an optimization, it is possible
165
281
to allocate an ``array_memory_block`` with extra memory at
166
282
the end to store the data with fewer memory allocations, in
167
283
which case the reference to the data contains NULL.
168
284
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.
171
289
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
173
293
allocator that doles out chunks of memory sequentially
174
294
for variable-sized data types. Due to the way nd::array
175
295
uses views, similar to NumPy, once some memory has been
@@ -178,20 +298,16 @@ deallocated until the whole memory block is freed.
178
298
A small exception is for reusable temporary buffers, and a
179
299
``reset`` operation is provided to support that use case.
180
300
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.
185
306
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
187
310
by a system external to DyND. For example, in some cases
188
311
DyND can directly map onto the string data of Python's
189
312
immutable strings, by using this type of memory block
190
313
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