carray 3.0.2 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +304 -0
- data/README.md +3 -4
- data/carray.gemspec +1 -1
- data/ext/ca_axis_dispatch.c +225 -0
- data/ext/ca_axis_group.c +177 -99
- data/ext/ca_binop_dispatch.c +54 -32
- data/ext/ca_binop_dispatch.h +1 -0
- data/ext/ca_categorical_iterator.c +66 -71
- data/ext/ca_compare.c +8 -2
- data/ext/ca_for_buffer.h +21 -68
- data/ext/ca_group_iter.c +27 -11
- data/ext/ca_kernel_iterator.c +663 -214
- data/ext/ca_kernel_iterator.h +231 -167
- data/ext/ca_monop_dispatch.c +4 -4
- data/ext/ca_monop_dispatch.h +4 -0
- data/ext/ca_obj_array.c +132 -22
- data/ext/ca_obj_bincmp.c +152 -121
- data/ext/ca_obj_binop.c +107 -210
- data/ext/ca_obj_bitarray.c +37 -24
- data/ext/ca_obj_bitfield.c +95 -62
- data/ext/ca_obj_block.c +1 -0
- data/ext/ca_obj_byte_swap.c +40 -40
- data/ext/ca_obj_const_string.c +96 -25
- data/ext/ca_obj_face.c +406 -64
- data/ext/ca_obj_face.h +92 -47
- data/ext/ca_obj_fake.c +21 -50
- data/ext/ca_obj_farray.c +1 -0
- data/ext/ca_obj_field.c +16 -3
- data/ext/ca_obj_fixlen_string.c +21 -21
- data/ext/ca_obj_grid.c +181 -124
- data/ext/ca_obj_meld.c +189 -107
- data/ext/ca_obj_moncmp.c +61 -61
- data/ext/ca_obj_monop.c +125 -107
- data/ext/ca_obj_object.c +543 -233
- data/ext/ca_obj_record.c +51 -16
- data/ext/ca_obj_reduce.c +5 -8
- data/ext/ca_obj_refer.c +117 -33
- data/ext/ca_obj_remap.c +57 -17
- data/ext/ca_obj_repeat.c +21 -5
- data/ext/ca_obj_roll.c +115 -11
- data/ext/ca_obj_select.c +47 -49
- data/ext/ca_obj_select_axis.c +58 -60
- data/ext/ca_obj_shift.c +22 -102
- data/ext/ca_obj_stack.c +223 -118
- data/ext/ca_obj_stride.c +195 -34
- data/ext/ca_obj_string.c +17 -18
- data/ext/ca_obj_tile.c +32 -16
- data/ext/ca_obj_time.c +23 -25
- data/ext/ca_obj_timedelta.c +21 -23
- data/ext/ca_obj_transpose.c +12 -3
- data/ext/ca_obj_triop.c +110 -117
- data/ext/ca_obj_window.c +149 -27
- data/ext/ca_op_ipower.c +24 -11
- data/ext/ca_op_powi.h +57 -30
- data/ext/ca_pow5_table.h +656 -0
- data/ext/ca_sort_kernels.h +70 -0
- data/ext/ca_sweep_engine.c +102 -79
- data/ext/ca_sweep_engine.h +7 -20
- data/ext/ca_triop_dispatch.c +4 -1
- data/ext/ca_triop_dispatch.h +5 -2
- data/ext/caframe_csv_reader.c +463 -0
- data/ext/carray.h +70 -27
- data/ext/carray_access.c +455 -211
- data/ext/carray_address_basis.c +177 -36
- data/ext/carray_attribute.c +45 -3
- data/ext/carray_bincount.c +32 -2
- data/ext/carray_broadcast.c +46 -14
- data/ext/carray_call_cfunc.c +0 -28
- data/ext/carray_cast.c +1444 -209
- data/ext/carray_cast_func.rb +34 -21
- data/ext/carray_conversion.c +197 -73
- data/ext/carray_copy.c +32 -11
- data/ext/carray_core.c +514 -122
- data/ext/carray_count.c +140 -87
- data/ext/carray_element.c +18 -27
- data/ext/carray_factorize.c +569 -277
- data/ext/carray_generate.c +76 -40
- data/ext/carray_histogram.c +152 -94
- data/ext/carray_hold.c +2 -1
- data/ext/carray_index_classifier.c +63 -96
- data/ext/carray_internal.h +385 -3
- data/ext/carray_lazy.c +834 -79
- data/ext/carray_loop.c +81 -65
- data/ext/carray_mask.c +682 -316
- data/ext/carray_math_kernel.h +1 -0
- data/ext/carray_median_percentile.c +221 -76
- data/ext/carray_memory_view.c +254 -248
- data/ext/carray_operator.c +1089 -359
- data/ext/carray_order.c +133 -69
- data/ext/carray_partition.c +102 -56
- data/ext/carray_random.c +273 -239
- data/ext/carray_scatter.c +308 -65
- data/ext/carray_segment.c +257 -0
- data/ext/carray_slab.c +170 -70
- data/ext/carray_sort.c +215 -218
- data/ext/carray_sort_kernel.c +8 -1
- data/ext/carray_struct.c +99 -21
- data/ext/carray_test.c +167 -64
- data/ext/carray_time_text.c +1182 -0
- data/ext/carray_utils.c +363 -98
- data/ext/extconf.rb +27 -2
- data/ext/mk_call_cfunc.rb +0 -2
- data/ext/mk_pow5_table.rb +35 -0
- data/ext/mkkernel.rb +1076 -846
- data/ext/ruby_carray.c +7 -1
- data/ext/version.h +4 -4
- data/ext/version.rb +4 -2
- data/lib/carray/attribute.rb +39 -0
- data/lib/carray/autoload_carray.rb +19 -0
- data/lib/carray/autoload_method_extension.rb +6 -0
- data/lib/carray/axis_group.rb +174 -26
- data/lib/carray/basics.rb +91 -25
- data/lib/carray/bincount_nd.rb +6 -0
- data/lib/carray/block_iterator.rb +118 -48
- data/lib/carray/boolean_reduce.rb +21 -29
- data/lib/carray/categorical.rb +94 -26
- data/lib/carray/categorical_iterator.rb +333 -826
- data/lib/carray/complex.rb +36 -29
- data/lib/carray/conditional.rb +94 -7
- data/lib/carray/const_string.rb +46 -0
- data/lib/carray/frame/concat.rb +157 -6
- data/lib/carray/frame/convert.rb +13 -7
- data/lib/carray/frame/csv_parser.rb +589 -82
- data/lib/carray/frame/describe.rb +79 -0
- data/lib/carray/frame/frame.rb +124 -25
- data/lib/carray/frame/group.rb +189 -63
- data/lib/carray/frame/io.rb +412 -72
- data/lib/carray/frame/join.rb +134 -46
- data/lib/carray/frame/records.rb +37 -16
- data/lib/carray/frame/reshape.rb +448 -0
- data/lib/carray/frame/sort.rb +26 -2
- data/lib/carray/frame/verbs.rb +715 -48
- data/lib/carray/frame.rb +2 -0
- data/lib/carray/fuse_source.rb +111 -2
- data/lib/carray/fusion.rb +229 -38
- data/lib/carray/inspect.rb +29 -11
- data/lib/carray/iterator.rb +14 -2
- data/lib/carray/lazy.rb +54 -30
- data/lib/carray/mask_gap_fill.rb +66 -52
- data/lib/carray/math.rb +32 -19
- data/lib/carray/meld_reduce.rb +40 -7
- data/lib/carray/methods/align_addr.rb +8 -4
- data/lib/carray/methods/bincount.rb +2 -2
- data/lib/carray/methods/bit_string.rb +14 -3
- data/lib/carray/methods/composition.rb +16 -10
- data/lib/carray/methods/factorize.rb +2 -2
- data/lib/carray/methods/gather_nd.rb +13 -2
- data/lib/carray/methods/insert_block.rb +9 -14
- data/lib/carray/methods/is_in.rb +117 -4
- data/lib/carray/methods/join.rb +1 -1
- data/lib/carray/methods/locate_addr.rb +177 -36
- data/lib/carray/methods/mode.rb +18 -1
- data/lib/carray/methods/repeat.rb +1 -20
- data/lib/carray/methods/resize.rb +21 -23
- data/lib/carray/methods/snap.rb +34 -12
- data/lib/carray/methods/unique.rb +11 -2
- data/lib/carray/record_order.rb +208 -0
- data/lib/carray/runtime.rb +14 -11
- data/lib/carray/segment_iterator.rb +990 -0
- data/lib/carray/serialize.rb +197 -27
- data/lib/carray/slab_iterator.rb +51 -27
- data/lib/carray/stack.rb +10 -4
- data/lib/carray/string_operation_extension.rb +4 -3
- data/lib/carray/struct.rb +142 -51
- data/lib/carray/struct_builder.rb +110 -14
- data/lib/carray/table.rb +2 -2
- data/lib/carray/time.rb +517 -103
- data/lib/carray/window_iterator.rb +127 -72
- data/lib/carray.rb +2 -2
- data/yard-stubs/ca_obj_array.rb +4 -4
- data/yard-stubs/ca_obj_bitarray.rb +7 -0
- data/yard-stubs/ca_obj_bitfield.rb +23 -12
- data/yard-stubs/ca_obj_fake.rb +1 -1
- data/yard-stubs/ca_obj_field.rb +1 -1
- data/yard-stubs/ca_obj_refer.rb +3 -3
- data/yard-stubs/ca_obj_roll.rb +0 -1
- data/yard-stubs/ca_obj_stride.rb +10 -7
- data/yard-stubs/ca_obj_transpose.rb +1 -1
- data/yard-stubs/ca_obj_window.rb +1 -2
- data/yard-stubs/carray_access.rb +5 -4
- data/yard-stubs/carray_broadcast.rb +1 -1
- data/yard-stubs/carray_cast.rb +78 -43
- data/yard-stubs/carray_conversion.rb +13 -1
- data/yard-stubs/carray_copy.rb +8 -3
- data/yard-stubs/carray_core.rb +3 -3
- data/yard-stubs/carray_count.rb +9 -0
- data/yard-stubs/carray_lazy.rb +5 -1
- data/yard-stubs/carray_loop.rb +4 -1
- data/yard-stubs/carray_mask.rb +34 -10
- data/yard-stubs/carray_math.rb +25 -13
- data/yard-stubs/carray_median_percentile.rb +10 -6
- data/yard-stubs/carray_order.rb +34 -13
- data/yard-stubs/carray_scatter.rb +10 -3
- data/yard-stubs/carray_segment.rb +72 -0
- data/yard-stubs/carray_slab.rb +2 -1
- data/yard-stubs/carray_sort.rb +43 -3
- data/yard-stubs/carray_test.rb +10 -0
- data/yard-stubs/carray_utils.rb +0 -26
- metadata +11 -19
- data/ext/ca_for_each_element.h +0 -239
- data/ext/carray_build_flags.h +0 -3
- data/ext/carray_config.h +0 -28
- data/ext/carray_kernels_bincmp.c +0 -4446
- data/ext/carray_kernels_binop.c +0 -11001
- data/ext/carray_kernels_init.c +0 -1131
- data/ext/carray_kernels_map.c +0 -3467
- data/ext/carray_kernels_moncmp.c +0 -2097
- data/ext/carray_kernels_monop.c +0 -18313
- data/ext/carray_kernels_reduce_aggregate.c +0 -26005
- data/ext/carray_kernels_reduce_boolean.c +0 -330
- data/ext/carray_kernels_reduce_cumulative.c +0 -14862
- data/ext/carray_kernels_reduce_extreme.c +0 -17494
- data/ext/carray_kernels_reduce_variance.c +0 -3910
- data/ext/carray_kernels_scan.c +0 -3693
- data/ext/carray_kernels_search.c +0 -32218
- data/ext/carray_kernels_sort.c +0 -10626
- data/ext/carray_kernels_triop.c +0 -1392
data/ext/ca_obj_meld.c
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
(sortedness-aware O(n+K) merge is a future
|
|
26
26
|
optimisation, memo §7.3)
|
|
27
27
|
fill_data: K-fold ca_fill
|
|
28
|
-
create_mask:
|
|
28
|
+
create_mask: mask CAMeld over the parents' masks (mirrors CAStack)
|
|
29
29
|
fold_stride: decline (return 0)
|
|
30
30
|
|
|
31
31
|
Design ref: devel/MEMO_CAMELD_SEGMENT_MAJOR_ENGINE.md. Meld-axis reduce
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
---------------------------------------------------------------------------- */
|
|
40
40
|
|
|
41
41
|
#include "carray.h"
|
|
42
|
-
#include "carray_internal.h" /* ca_attach_all */
|
|
42
|
+
#include "carray_internal.h" /* ca_attach_all / ca_sync_all */
|
|
43
43
|
#include "ca_obj_face.h" /* ca_face_state_portable */
|
|
44
44
|
|
|
45
45
|
/* ------------------------------------------------------------------- */
|
|
@@ -112,9 +112,9 @@ ca_meld_check_uniform (int32_t n_parents, CArray **parents, int8_t meld_axis)
|
|
|
112
112
|
CArray *p = parents[i];
|
|
113
113
|
if ( p->data_type != ref->data_type ) {
|
|
114
114
|
rb_raise(rb_eArgError,
|
|
115
|
-
"
|
|
116
|
-
"(
|
|
117
|
-
ref->data_type, i, p->data_type);
|
|
115
|
+
"meld: the arrays must have the same data type "
|
|
116
|
+
"(array 0 is %s, array %d is %s)",
|
|
117
|
+
ca_type_name[ref->data_type], i, ca_type_name[p->data_type]);
|
|
118
118
|
}
|
|
119
119
|
if ( p->ndim != ref->ndim ) {
|
|
120
120
|
rb_raise(rb_eArgError,
|
|
@@ -181,6 +181,8 @@ ca_meld_setup (CAMeld *ca, int32_t n_parents, CArray **parents, int8_t meld_axis
|
|
|
181
181
|
ca->attach = 0;
|
|
182
182
|
ca->nosync = 0;
|
|
183
183
|
|
|
184
|
+
ca->mask_standins = NULL;
|
|
185
|
+
ca->mask_owner = NULL;
|
|
184
186
|
ca->n_parents = n_parents;
|
|
185
187
|
ca->parents = ALLOC_N(CArray *, n_parents);
|
|
186
188
|
for ( i = 0; i < n_parents; i++ ) {
|
|
@@ -224,6 +226,13 @@ free_ca_meld (void *ap)
|
|
|
224
226
|
CAMeld *ca = (CAMeld *) ap;
|
|
225
227
|
if ( ca != NULL ) {
|
|
226
228
|
ca_free(ca->mask);
|
|
229
|
+
if ( ca->mask_standins ) {
|
|
230
|
+
int32_t k;
|
|
231
|
+
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
232
|
+
if ( ca->mask_standins[k] ) ca_free(ca->mask_standins[k]);
|
|
233
|
+
}
|
|
234
|
+
xfree(ca->mask_standins);
|
|
235
|
+
}
|
|
227
236
|
xfree(ca->seg_offset);
|
|
228
237
|
xfree(ca->parents);
|
|
229
238
|
xfree(ca->dim);
|
|
@@ -273,10 +282,33 @@ ca_meld_tail_elements (const CAMeld *ca)
|
|
|
273
282
|
|
|
274
283
|
/* view[..., v at meld_axis, ...] = parents[k][..., v - seg_offset[k], ...]
|
|
275
284
|
where k = segment_of(v). */
|
|
285
|
+
/* On the mask of a CAMeld: let its stand-ins give way to the parents' own
|
|
286
|
+
masks (see ca_multi_parent_mask_refresh). */
|
|
287
|
+
static void
|
|
288
|
+
ca_meld_mask_refresh (CAMeld *ca, int for_write)
|
|
289
|
+
{
|
|
290
|
+
CAMeld *o = (CAMeld *) ca->mask_owner;
|
|
291
|
+
if ( o != NULL ) {
|
|
292
|
+
ca_multi_parent_mask_refresh((CArray *) ca, o->parents, o->mask_standins,
|
|
293
|
+
o->n_parents, for_write);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
static void
|
|
298
|
+
ca_meld_mask_settle (CAMeld *ca)
|
|
299
|
+
{
|
|
300
|
+
CAMeld *o = (CAMeld *) ca->mask_owner;
|
|
301
|
+
if ( o != NULL ) {
|
|
302
|
+
ca_multi_parent_mask_settle((CArray *) ca, o->parents, o->mask_standins,
|
|
303
|
+
o->n_parents);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
276
307
|
static void
|
|
277
308
|
ca_meld_func_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
278
309
|
{
|
|
279
310
|
CAMeld *ca = (CAMeld *) ap;
|
|
311
|
+
ca_meld_mask_refresh(ca, dir == CA_XFER_PUT);
|
|
280
312
|
int8_t ma = ca->meld_axis;
|
|
281
313
|
ca_size_t v = idx[ma];
|
|
282
314
|
int32_t k;
|
|
@@ -311,6 +343,7 @@ ca_meld_func_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs,
|
|
|
311
343
|
void *data, int dir)
|
|
312
344
|
{
|
|
313
345
|
CAMeld *ca = (CAMeld *) ap;
|
|
346
|
+
ca_meld_mask_refresh(ca, dir == CA_XFER_PUT);
|
|
314
347
|
int8_t ma = ca->meld_axis;
|
|
315
348
|
ca_size_t bytes = ca->bytes;
|
|
316
349
|
ca_size_t view_div[CA_RANK_MAX]; /* row-major divisor per view axis */
|
|
@@ -606,7 +639,9 @@ static void
|
|
|
606
639
|
ca_meld_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
607
640
|
ca_size_t *strides, void *data, int dir)
|
|
608
641
|
{
|
|
642
|
+
if ( ca_region_is_empty(((CArray *) ap)->ndim, counts) ) return;
|
|
609
643
|
CAMeld *ca = (CAMeld *) ap;
|
|
644
|
+
ca_meld_mask_refresh(ca, dir == CA_XFER_PUT);
|
|
610
645
|
int8_t ma = ca->meld_axis;
|
|
611
646
|
ca_size_t native[CA_RANK_MAX];
|
|
612
647
|
ca_size_t s;
|
|
@@ -616,31 +651,27 @@ ca_meld_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
616
651
|
s = ca->bytes;
|
|
617
652
|
for ( i = ca->ndim - 1; i >= 0; i-- ) { native[i] = s; s *= ca->dim[i]; }
|
|
618
653
|
|
|
654
|
+
/* Structural iff strides == native and the request is a box over the
|
|
655
|
+
view's own axes. Equal strides alone are not enough: a size-1 axis
|
|
656
|
+
gives two axes the same native stride, and a flat window reshaped back
|
|
657
|
+
to ndim has native strides yet wraps across an axis. The request is
|
|
658
|
+
over the view's addresses; see ca_xfer_stride_request_is_axis_box
|
|
659
|
+
(carray.h). Inside the gate the step on every axis is 1 and the region
|
|
660
|
+
stays inside each axis, which ca_meld_xfer_stride_ma_internal (handed
|
|
661
|
+
no strides) depends on. */
|
|
619
662
|
for ( i = 0; i < ca->ndim; i++ ) {
|
|
620
663
|
if ( strides[i] != native[i] ) { structural = 0; break; }
|
|
621
664
|
}
|
|
665
|
+
if ( structural &&
|
|
666
|
+
! ca_xfer_stride_request_is_axis_box(ca, starts, counts, strides) ) {
|
|
667
|
+
structural = 0;
|
|
668
|
+
}
|
|
622
669
|
|
|
623
|
-
if ( ! structural ) {
|
|
670
|
+
if ( ! structural || ! ca_fast_paths_enabled() ) {
|
|
624
671
|
ca_meld_xfer_stride_per_cell(ca, starts, counts, strides, data, dir);
|
|
625
672
|
return;
|
|
626
673
|
}
|
|
627
674
|
|
|
628
|
-
/* Bound check on meld_axis, after the gate and not before it. Only once
|
|
629
|
-
strides == native is established does request axis ma mean view axis ma;
|
|
630
|
-
asked earlier, strides[ma] / native[ma] is not a step along the meld axis
|
|
631
|
-
and legal requests get rejected. Inside the gate the step is 1, so the
|
|
632
|
-
region is starts[ma] .. starts[ma] + counts[ma]. ca_meld_xfer_stride_ma_
|
|
633
|
-
internal below is handed no strides at all and depends on both facts. */
|
|
634
|
-
{
|
|
635
|
-
ca_size_t req_lo = starts[ma];
|
|
636
|
-
ca_size_t req_hi = starts[ma] + counts[ma];
|
|
637
|
-
if ( counts[ma] > 0 && ( req_lo < 0 || req_hi > ca->dim[ma] ) ) {
|
|
638
|
-
rb_raise(rb_eIndexError,
|
|
639
|
-
"CAMeld xfer_stride meld_axis (axis %d) [%lld, %lld) out of range [0, %lld)",
|
|
640
|
-
(int) ma, (long long) req_lo, (long long) req_hi, (long long) ca->dim[ma]);
|
|
641
|
-
}
|
|
642
|
-
}
|
|
643
|
-
|
|
644
675
|
if ( ma == 0 ) {
|
|
645
676
|
ca_meld_xfer_stride_ma0(ca, starts, counts, strides, data, dir);
|
|
646
677
|
} else {
|
|
@@ -652,15 +683,37 @@ ca_meld_func_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
|
652
683
|
/* xfer_all */
|
|
653
684
|
/* ------------------------------------------------------------------- */
|
|
654
685
|
|
|
686
|
+
/* A parent's cells, delivered (PUT). into_buffers writes them into the
|
|
687
|
+
buffer the parent's attach handed out, rather than through the parent to
|
|
688
|
+
what is behind it: the sync of an attached meld, which then syncs each
|
|
689
|
+
parent. Writing past the buffer would leave it stale, and the parent's
|
|
690
|
+
own sync would push the stale buffer back over the cells just written. */
|
|
691
|
+
static void
|
|
692
|
+
ca_meld_put_parent (CArray *p, char *src, int into_buffers)
|
|
693
|
+
{
|
|
694
|
+
if ( into_buffers ) {
|
|
695
|
+
memcpy(p->ptr, src, (size_t) (p->elements * p->bytes));
|
|
696
|
+
}
|
|
697
|
+
else {
|
|
698
|
+
ca_xfer_all(p, src, CA_XFER_PUT);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
655
702
|
/* meld_axis == 0 best path: K contig xfer_all at prefix-sum offsets. */
|
|
656
703
|
static void
|
|
657
|
-
ca_meld_xfer_all_ma0 (CAMeld *ca, void *data, int dir)
|
|
704
|
+
ca_meld_xfer_all_ma0 (CAMeld *ca, void *data, int dir, int into_buffers)
|
|
658
705
|
{
|
|
659
706
|
ca_size_t tail_bytes = ca_meld_tail_elements(ca) * ca->bytes;
|
|
660
707
|
char *d = (char *) data;
|
|
661
708
|
int32_t k;
|
|
662
709
|
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
663
|
-
|
|
710
|
+
char *seg = d + ca->seg_offset[k] * tail_bytes;
|
|
711
|
+
if ( dir == CA_XFER_PUT ) {
|
|
712
|
+
ca_meld_put_parent(ca->parents[k], seg, into_buffers);
|
|
713
|
+
}
|
|
714
|
+
else {
|
|
715
|
+
ca_xfer_all(ca->parents[k], seg, dir);
|
|
716
|
+
}
|
|
664
717
|
}
|
|
665
718
|
}
|
|
666
719
|
|
|
@@ -677,7 +730,8 @@ ca_meld_xfer_all_ma0 (CAMeld *ca, void *data, int dir)
|
|
|
677
730
|
The naive per-cell odometer that this replaces cost ~2x eager on M2;
|
|
678
731
|
chunked memcpy approaches memcpy bandwidth (eager parity target). */
|
|
679
732
|
static void
|
|
680
|
-
ca_meld_xfer_all_ma_internal (CAMeld *ca, void *data, int dir
|
|
733
|
+
ca_meld_xfer_all_ma_internal (CAMeld *ca, void *data, int dir,
|
|
734
|
+
int into_buffers)
|
|
681
735
|
{
|
|
682
736
|
int8_t ma = ca->meld_axis;
|
|
683
737
|
int8_t ndim = ca->ndim;
|
|
@@ -762,23 +816,29 @@ ca_meld_xfer_all_ma_internal (CAMeld *ca, void *data, int dir)
|
|
|
762
816
|
}
|
|
763
817
|
|
|
764
818
|
if ( dir == CA_XFER_PUT ) {
|
|
765
|
-
|
|
819
|
+
ca_meld_put_parent(p, buf, into_buffers);
|
|
766
820
|
}
|
|
767
821
|
ALLOCV_END(holder);
|
|
768
822
|
}
|
|
769
823
|
}
|
|
770
824
|
|
|
771
825
|
static void
|
|
772
|
-
|
|
826
|
+
ca_meld_xfer_parents (CAMeld *ca, void *data, int dir, int into_buffers)
|
|
773
827
|
{
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
ca_meld_xfer_all_ma0(ca, data, dir);
|
|
828
|
+
if ( ca->meld_axis == 0 && ca_fast_paths_enabled() ) {
|
|
829
|
+
ca_meld_xfer_all_ma0(ca, data, dir, into_buffers);
|
|
777
830
|
} else {
|
|
778
|
-
ca_meld_xfer_all_ma_internal(ca, data, dir);
|
|
831
|
+
ca_meld_xfer_all_ma_internal(ca, data, dir, into_buffers);
|
|
779
832
|
}
|
|
780
833
|
}
|
|
781
834
|
|
|
835
|
+
static void
|
|
836
|
+
ca_meld_func_xfer_all (void *ap, void *data, int dir)
|
|
837
|
+
{
|
|
838
|
+
ca_meld_mask_refresh((CAMeld *) ap, dir == CA_XFER_PUT);
|
|
839
|
+
ca_meld_xfer_parents((CAMeld *) ap, data, dir, 0);
|
|
840
|
+
}
|
|
841
|
+
|
|
782
842
|
/* ------------------------------------------------------------------- */
|
|
783
843
|
/* attach / sync / detach */
|
|
784
844
|
/* ------------------------------------------------------------------- */
|
|
@@ -787,28 +847,42 @@ static void
|
|
|
787
847
|
ca_meld_func_allocate (void *ap)
|
|
788
848
|
{
|
|
789
849
|
CAMeld *ca = (CAMeld *) ap;
|
|
850
|
+
ca_meld_mask_refresh(ca, 0);
|
|
790
851
|
ca_attach_all(ca->parents, ca->n_parents);
|
|
791
852
|
ca->ptr = xmalloc(ca_length(ca));
|
|
792
853
|
}
|
|
793
854
|
|
|
855
|
+
static VALUE
|
|
856
|
+
ca_meld_attach_owned (VALUE arg)
|
|
857
|
+
{
|
|
858
|
+
ca_axis_view_attach_owned((void *) arg);
|
|
859
|
+
return Qnil;
|
|
860
|
+
}
|
|
861
|
+
|
|
794
862
|
static void
|
|
795
863
|
ca_meld_func_attach (void *ap)
|
|
796
864
|
{
|
|
797
865
|
CAMeld *ca = (CAMeld *) ap;
|
|
866
|
+
ca_meld_mask_refresh(ca, 0);
|
|
867
|
+
int32_t k;
|
|
868
|
+
int tag = 0;
|
|
798
869
|
ca_attach_all(ca->parents, ca->n_parents);
|
|
799
|
-
|
|
800
|
-
|
|
870
|
+
rb_protect(ca_meld_attach_owned, (VALUE) ca, &tag);
|
|
871
|
+
if ( tag ) {
|
|
872
|
+
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
873
|
+
ca_detach(ca->parents[k]);
|
|
874
|
+
}
|
|
875
|
+
rb_jump_tag(tag);
|
|
876
|
+
}
|
|
801
877
|
}
|
|
802
878
|
|
|
803
879
|
static void
|
|
804
880
|
ca_meld_func_sync (void *ap)
|
|
805
881
|
{
|
|
806
882
|
CAMeld *ca = (CAMeld *) ap;
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
ca_sync(ca->parents[k]);
|
|
811
|
-
}
|
|
883
|
+
ca_meld_xfer_parents(ca, ca->ptr, CA_XFER_PUT, 1);
|
|
884
|
+
ca_sync_all(ca->parents, ca->n_parents);
|
|
885
|
+
ca_meld_mask_settle(ca);
|
|
812
886
|
}
|
|
813
887
|
|
|
814
888
|
static void
|
|
@@ -831,6 +905,7 @@ static void
|
|
|
831
905
|
ca_meld_func_fill_data (void *ap, void *ptr)
|
|
832
906
|
{
|
|
833
907
|
CAMeld *ca = (CAMeld *) ap;
|
|
908
|
+
ca_meld_mask_refresh(ca, 1);
|
|
834
909
|
int32_t k;
|
|
835
910
|
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
836
911
|
ca_fill(ca->parents[k], ptr);
|
|
@@ -838,7 +913,7 @@ ca_meld_func_fill_data (void *ap, void *ptr)
|
|
|
838
913
|
}
|
|
839
914
|
|
|
840
915
|
/* ------------------------------------------------------------------- */
|
|
841
|
-
/* create_mask (
|
|
916
|
+
/* create_mask (mirrors CAStack) */
|
|
842
917
|
/* ------------------------------------------------------------------- */
|
|
843
918
|
|
|
844
919
|
static void
|
|
@@ -850,14 +925,16 @@ ca_meld_func_create_mask (void *ap)
|
|
|
850
925
|
int32_t k;
|
|
851
926
|
|
|
852
927
|
mask_parents = ALLOCV_N(CArray *, holder, ca->n_parents);
|
|
928
|
+
if ( ! ca->mask_standins ) {
|
|
929
|
+
ca->mask_standins = ALLOC_N(CArray *, ca->n_parents);
|
|
930
|
+
MEMZERO(ca->mask_standins, CArray *, ca->n_parents);
|
|
931
|
+
}
|
|
853
932
|
for ( k = 0; k < ca->n_parents; k++ ) {
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
ca_create_mask(ca->parents[k]);
|
|
857
|
-
}
|
|
858
|
-
mask_parents[k] = ca->parents[k]->mask;
|
|
933
|
+
mask_parents[k] = ca_multi_parent_mask(ca->parents[k],
|
|
934
|
+
&ca->mask_standins[k]);
|
|
859
935
|
}
|
|
860
936
|
ca->mask = (CArray *) ca_meld_new(ca->n_parents, mask_parents, ca->meld_axis);
|
|
937
|
+
((CAMeld *) ca->mask)->mask_owner = (CArray *) ca;
|
|
861
938
|
ALLOCV_END(holder);
|
|
862
939
|
}
|
|
863
940
|
|
|
@@ -876,6 +953,56 @@ ca_meld_func_fold_stride (void *ap, ca_fold_t *f, void **next_parent)
|
|
|
876
953
|
/* operation table */
|
|
877
954
|
/* ------------------------------------------------------------------- */
|
|
878
955
|
|
|
956
|
+
/* The table's write slots: after a write, refuse a true that reached the
|
|
957
|
+
stand-in of a value array or a mask array (ca_multi_parent_mask_check).
|
|
958
|
+
Only the mask of a CAMeld has stand-ins to check. */
|
|
959
|
+
static void
|
|
960
|
+
ca_meld_mask_check (CAMeld *ca)
|
|
961
|
+
{
|
|
962
|
+
CAMeld *o = (CAMeld *) ca->mask_owner;
|
|
963
|
+
if ( o != NULL ) {
|
|
964
|
+
ca_multi_parent_mask_check((CArray *) ca, o->parents, o->mask_standins,
|
|
965
|
+
o->n_parents);
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
static void
|
|
970
|
+
ca_meld_put_xfer_index (void *ap, ca_size_t *idx, void *data, int dir)
|
|
971
|
+
{
|
|
972
|
+
ca_meld_func_xfer_index(ap, idx, data, dir);
|
|
973
|
+
if ( dir == CA_XFER_PUT ) ca_meld_mask_check((CAMeld *) ap);
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
static void
|
|
977
|
+
ca_meld_put_xfer_addrs (void *ap, ca_size_t n, ca_size_t *addrs, void *data,
|
|
978
|
+
int dir)
|
|
979
|
+
{
|
|
980
|
+
ca_meld_func_xfer_addrs(ap, n, addrs, data, dir);
|
|
981
|
+
if ( dir == CA_XFER_PUT ) ca_meld_mask_check((CAMeld *) ap);
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
static void
|
|
985
|
+
ca_meld_put_xfer_stride (void *ap, ca_size_t *starts, ca_size_t *counts,
|
|
986
|
+
ca_size_t *strides, void *data, int dir)
|
|
987
|
+
{
|
|
988
|
+
ca_meld_func_xfer_stride(ap, starts, counts, strides, data, dir);
|
|
989
|
+
if ( dir == CA_XFER_PUT ) ca_meld_mask_check((CAMeld *) ap);
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
static void
|
|
993
|
+
ca_meld_put_xfer_all (void *ap, void *data, int dir)
|
|
994
|
+
{
|
|
995
|
+
ca_meld_func_xfer_all(ap, data, dir);
|
|
996
|
+
if ( dir == CA_XFER_PUT ) ca_meld_mask_check((CAMeld *) ap);
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
static void
|
|
1000
|
+
ca_meld_put_fill_data (void *ap, void *ptr)
|
|
1001
|
+
{
|
|
1002
|
+
ca_meld_func_fill_data(ap, ptr);
|
|
1003
|
+
ca_meld_mask_check((CAMeld *) ap);
|
|
1004
|
+
}
|
|
1005
|
+
|
|
879
1006
|
ca_operation_function_t ca_meld_func = {
|
|
880
1007
|
-1, /* CA_OBJ_MELD */
|
|
881
1008
|
CA_VIEW_ARRAY,
|
|
@@ -885,30 +1012,19 @@ ca_operation_function_t ca_meld_func = {
|
|
|
885
1012
|
ca_meld_func_attach,
|
|
886
1013
|
ca_meld_func_sync,
|
|
887
1014
|
ca_meld_func_detach,
|
|
888
|
-
|
|
1015
|
+
ca_meld_put_fill_data,
|
|
889
1016
|
ca_meld_func_create_mask,
|
|
890
|
-
|
|
891
|
-
|
|
1017
|
+
ca_meld_put_xfer_index,
|
|
1018
|
+
ca_meld_put_xfer_addrs,
|
|
892
1019
|
ca_meld_func_fold_stride,
|
|
893
|
-
|
|
894
|
-
|
|
1020
|
+
ca_meld_put_xfer_stride,
|
|
1021
|
+
ca_meld_put_xfer_all,
|
|
895
1022
|
};
|
|
896
1023
|
|
|
897
1024
|
/* ------------------------------------------------------------------- */
|
|
898
1025
|
/* Ruby surface */
|
|
899
1026
|
/* ------------------------------------------------------------------- */
|
|
900
1027
|
|
|
901
|
-
/* One-level strip of a Face VALUE to its storage-side parent (non-Face as-is).
|
|
902
|
-
Keeps the @parent ivar in step with the pre-stripped C parents, so the
|
|
903
|
-
Ruby-visible chain of a melded Face is single-Face too. */
|
|
904
|
-
static VALUE
|
|
905
|
-
ca_meld_face_parent1 (VALUE v)
|
|
906
|
-
{
|
|
907
|
-
CArray *c;
|
|
908
|
-
TypedData_Get_Struct(v, CArray, &carray_data_type, c);
|
|
909
|
-
return ca_is_face(c) ? rb_ca_parent(v) : v;
|
|
910
|
-
}
|
|
911
|
-
|
|
912
1028
|
VALUE
|
|
913
1029
|
rb_ca_meld_new (VALUE parents_ary, int8_t meld_axis)
|
|
914
1030
|
{
|
|
@@ -932,7 +1048,7 @@ rb_ca_meld_new (VALUE parents_ary, int8_t meld_axis)
|
|
|
932
1048
|
ca = ca_meld_new((int32_t) n, parents, meld_axis);
|
|
933
1049
|
obj = ca_wrap_struct(ca);
|
|
934
1050
|
rb_ivar_set(obj, id_parents, rb_ary_dup(parents_ary));
|
|
935
|
-
rb_ca_set_parent(obj,
|
|
1051
|
+
rb_ca_set_parent(obj, ca_face_strip_one(rb_ary_entry(parents_ary, 0)));
|
|
936
1052
|
ALLOCV_END(holder);
|
|
937
1053
|
return obj;
|
|
938
1054
|
}
|
|
@@ -949,8 +1065,14 @@ rb_ca_meld_initialize_copy (VALUE self, VALUE other)
|
|
|
949
1065
|
{
|
|
950
1066
|
CAMeld *ca, *cs;
|
|
951
1067
|
TypedData_Get_Struct(self, CAMeld, &cameld_data_type, ca);
|
|
1068
|
+
ca_check_uninitialized(ca);
|
|
952
1069
|
TypedData_Get_Struct(other, CAMeld, &cameld_data_type, cs);
|
|
953
1070
|
ca_meld_setup(ca, cs->n_parents, cs->parents, cs->meld_axis);
|
|
1071
|
+
/* A copy of a meld's mask reads and writes the same stand-ins, so it
|
|
1072
|
+
answers to the same owner: its writes reach the parents' masks. The
|
|
1073
|
+
copy holds the owner alive through the masked_array ivar that dup
|
|
1074
|
+
carries over (see rb_ca_mask_array). */
|
|
1075
|
+
ca->mask_owner = cs->mask_owner;
|
|
954
1076
|
return self;
|
|
955
1077
|
}
|
|
956
1078
|
|
|
@@ -981,6 +1103,7 @@ rb_ca_meld_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
981
1103
|
NUM2LONG(axis_val), (int) ref->ndim, "CAMeld.new");
|
|
982
1104
|
}
|
|
983
1105
|
TypedData_Get_Struct(self, CAMeld, &cameld_data_type, ca);
|
|
1106
|
+
ca_check_uninitialized(ca);
|
|
984
1107
|
parents = ALLOCV_N(CArray *, holder, n);
|
|
985
1108
|
for ( i = 0; i < n; i++ ) {
|
|
986
1109
|
VALUE p = rb_ary_entry(list, i);
|
|
@@ -989,7 +1112,7 @@ rb_ca_meld_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
989
1112
|
}
|
|
990
1113
|
ca_meld_setup(ca, (int32_t) n, parents, meld_axis);
|
|
991
1114
|
rb_ivar_set(self, id_parents, rb_ary_dup(list));
|
|
992
|
-
rb_ca_set_parent(self,
|
|
1115
|
+
rb_ca_set_parent(self, ca_face_strip_one(rb_ary_entry(list, 0)));
|
|
993
1116
|
ALLOCV_END(holder);
|
|
994
1117
|
return self;
|
|
995
1118
|
}
|
|
@@ -1011,61 +1134,20 @@ rb_ca_meld_initialize (int argc, VALUE *argv, VALUE self)
|
|
|
1011
1134
|
static VALUE
|
|
1012
1135
|
rb_ca_meld_s_new (int argc, VALUE *argv, VALUE klass)
|
|
1013
1136
|
{
|
|
1014
|
-
VALUE list, kwargs;
|
|
1015
|
-
long n, i;
|
|
1016
|
-
int all_face = 1;
|
|
1017
|
-
VALUE face_class = Qnil;
|
|
1018
|
-
CArray *ref_face = NULL;
|
|
1137
|
+
VALUE list, kwargs, face_class;
|
|
1019
1138
|
VALUE obj;
|
|
1020
1139
|
|
|
1021
1140
|
rb_scan_args(argc, argv, "1:", &list, &kwargs);
|
|
1022
1141
|
Check_Type(list, T_ARRAY);
|
|
1023
|
-
|
|
1024
|
-
if ( n <= 0 ) {
|
|
1142
|
+
if ( RARRAY_LEN(list) <= 0 ) {
|
|
1025
1143
|
rb_raise(rb_eArgError, "CAMeld.new requires at least one parent");
|
|
1026
1144
|
}
|
|
1027
|
-
|
|
1028
|
-
for ( i = 0; i < n; i++ ) {
|
|
1029
|
-
VALUE p = rb_ary_entry(list, i);
|
|
1030
|
-
CArray *ca;
|
|
1031
|
-
rb_check_carray_object(p);
|
|
1032
|
-
TypedData_Get_Struct(p, CArray, &carray_data_type, ca);
|
|
1033
|
-
if ( !ca_is_face(ca) ) { all_face = 0; break; }
|
|
1034
|
-
if ( i == 0 ) {
|
|
1035
|
-
face_class = rb_obj_class(p);
|
|
1036
|
-
ref_face = ca;
|
|
1037
|
-
} else if ( rb_obj_class(p) != face_class ) {
|
|
1038
|
-
all_face = 0; break;
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
|
|
1042
|
-
/* A single parent has nothing to weld against, so its Face rides the
|
|
1043
|
-
chain as it always did; refuse and lift only apply from two up. */
|
|
1044
|
-
if ( all_face && n > 1
|
|
1045
|
-
&& !ca_face_state_portable(ref_face->obj_type, face_class) ) {
|
|
1046
|
-
rb_raise(rb_eArgError,
|
|
1047
|
-
"CAMeld.new: %s state is not portable across multiple "
|
|
1048
|
-
"parents (= per-parent storage like CAConstString's buffer); "
|
|
1049
|
-
"strip Face with .parent if a storage-level CAMeld is intended",
|
|
1050
|
-
rb_class2name(face_class));
|
|
1051
|
-
}
|
|
1145
|
+
face_class = ca_face_list_class(list, "CAMeld.new");
|
|
1052
1146
|
|
|
1053
1147
|
obj = rb_obj_alloc(klass);
|
|
1054
1148
|
rb_obj_call_init_kw(obj, argc, argv, RB_PASS_CALLED_KEYWORDS);
|
|
1055
1149
|
|
|
1056
|
-
if (
|
|
1057
|
-
|
|
1058
|
-
for ( i = 1; i < n; i++ ) {
|
|
1059
|
-
VALUE p = rb_ary_entry(list, i);
|
|
1060
|
-
CArray *ca;
|
|
1061
|
-
TypedData_Get_Struct(p, CArray, &carray_data_type, ca);
|
|
1062
|
-
if ( !ca_face_state_compatible(rb_ary_entry(list, 0), ref_face, p, ca) ) {
|
|
1063
|
-
rb_raise(rb_eArgError,
|
|
1064
|
-
"CAMeld.new: Face state mismatch across parents "
|
|
1065
|
-
"(= %s instance at index %ld differs in state from index 0)",
|
|
1066
|
-
rb_class2name(face_class), i);
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1150
|
+
if ( NIL_P(face_class) ) return obj;
|
|
1069
1151
|
return ca_face_lift(obj, rb_ary_entry(list, 0));
|
|
1070
1152
|
}
|
|
1071
1153
|
|