Skip to content

Commit f53cd76

Browse files
wlevinetranslunar
authored andcommitted
Avoid unnecessary heap allocation of SLICE objects (#542)
1 parent c121885 commit f53cd76

File tree

1 file changed

+22
-39
lines changed

1 file changed

+22
-39
lines changed

ext/nmatrix/ruby_nmatrix.c

Lines changed: 22 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ static VALUE nm_each_stored_with_indices(VALUE nmatrix);
5353
static VALUE nm_each_ordered_stored_with_indices(VALUE nmatrix);
5454
static VALUE nm_map_stored(VALUE nmatrix);
5555

56-
static SLICE* get_slice(size_t dim, int argc, VALUE* arg, size_t* shape);
56+
static void init_slice_no_alloc(SLICE* slice, size_t dim, int argc, VALUE* arg, size_t* shape);
5757
static VALUE nm_xslice(int argc, VALUE* argv, void* (*slice_func)(const STORAGE*, SLICE*), void (*delete_func)(NMATRIX*), VALUE self);
5858
static VALUE nm_mset(int argc, VALUE* argv, VALUE self);
5959
static VALUE nm_mget(int argc, VALUE* argv, VALUE self);
@@ -398,28 +398,6 @@ void Init_nmatrix() {
398398
// Ruby Methods //
399399
//////////////////
400400

401-
402-
/*
403-
* Slice constructor.
404-
*/
405-
static SLICE* alloc_slice(size_t dim) {
406-
SLICE* slice = NM_ALLOC(SLICE);
407-
slice->coords = NM_ALLOC_N(size_t, dim);
408-
slice->lengths = NM_ALLOC_N(size_t, dim);
409-
return slice;
410-
}
411-
412-
413-
/*
414-
* Slice destructor.
415-
*/
416-
static void free_slice(SLICE* slice) {
417-
NM_FREE(slice->coords);
418-
NM_FREE(slice->lengths);
419-
NM_FREE(slice);
420-
}
421-
422-
423401
/*
424402
* Allocator.
425403
*/
@@ -1272,7 +1250,12 @@ static VALUE nm_init_new_version(int argc, VALUE* argv, VALUE self) {
12721250
tmp_shape[m] = shape[m];
12731251
}
12741252

1275-
SLICE* slice = get_slice(dim, dim, slice_argv, shape);
1253+
SLICE slice_s;
1254+
SLICE* slice = &slice_s;
1255+
slice->coords = NM_ALLOCA_N(size_t, dim);
1256+
slice->lengths = NM_ALLOCA_N(size_t, dim);
1257+
init_slice_no_alloc(slice, dim, dim, slice_argv, shape);
1258+
12761259
// Create a temporary dense matrix and use it to do a slice assignment on self.
12771260
NMATRIX* tmp = nm_create(nm::DENSE_STORE, (STORAGE*)nm_dense_storage_create(dtype, tmp_shape, dim, v, v_size));
12781261
nm_register_nmatrix(tmp);
@@ -1282,8 +1265,6 @@ static VALUE nm_init_new_version(int argc, VALUE* argv, VALUE self) {
12821265
if (stype == nm::YALE_STORE) nm_yale_storage_set(self, slice, rb_tmp);
12831266
else nm_list_storage_set(self, slice, rb_tmp);
12841267

1285-
free_slice(slice);
1286-
12871268
// We need to free v if it's not the same size as tmp -- because tmp will have made a copy instead.
12881269
//if (nm_storage_count_max_elements(tmp->storage) != v_size)
12891270
// NM_FREE(v);
@@ -2018,7 +1999,11 @@ static VALUE nm_mset(int argc, VALUE* argv, VALUE self) {
20181999
NM_CONSERVATIVE(nm_register_value(&self));
20192000
NM_CONSERVATIVE(nm_register_values(argv, argc));
20202001

2021-
SLICE* slice = get_slice(dim, argc-1, argv, NM_STORAGE(self)->shape);
2002+
SLICE slice_s;
2003+
SLICE* slice = &slice_s;
2004+
slice->coords = NM_ALLOCA_N(size_t, dim);
2005+
slice->lengths = NM_ALLOCA_N(size_t, dim);
2006+
init_slice_no_alloc(slice, dim, argc-1, argv, NM_STORAGE(self)->shape);
20222007

20232008
static void (*ttable[nm::NUM_STYPES])(VALUE, SLICE*, VALUE) = {
20242009
nm_dense_storage_set,
@@ -2028,8 +2013,6 @@ static VALUE nm_mset(int argc, VALUE* argv, VALUE self) {
20282013

20292014
ttable[NM_STYPE(self)](self, slice, argv[argc-1]);
20302015

2031-
free_slice(slice);
2032-
20332016
to_return = argv[argc-1];
20342017

20352018
NM_CONSERVATIVE(nm_unregister_value(&self));
@@ -2259,7 +2242,12 @@ static VALUE nm_xslice(int argc, VALUE* argv, void* (*slice_func)(const STORAGE*
22592242

22602243
nm_register_value(&result);
22612244

2262-
SLICE* slice = get_slice(NM_DIM(self), argc, argv, s->shape);
2245+
SLICE slice_s;
2246+
SLICE* slice = &slice_s;
2247+
size_t dim = NM_DIM(self);
2248+
slice->coords = NM_ALLOCA_N(size_t, dim);
2249+
slice->lengths = NM_ALLOCA_N(size_t, dim);
2250+
init_slice_no_alloc(slice, dim, argc, argv, s->shape);
22632251

22642252
if (slice->single) {
22652253
static void* (*ttable[nm::NUM_STYPES])(const STORAGE*, SLICE*) = {
@@ -2280,8 +2268,6 @@ static VALUE nm_xslice(int argc, VALUE* argv, void* (*slice_func)(const STORAGE*
22802268
result = Data_Wrap_Struct(CLASS_OF(self), nm_mark, delete_func, mat);
22812269
nm_unregister_nmatrix(mat);
22822270
}
2283-
2284-
free_slice(slice);
22852271
}
22862272

22872273
nm_unregister_value(&result);
@@ -2623,19 +2609,17 @@ nm::dtype_t nm_dtype_guess(VALUE v) {
26232609
}
26242610
}
26252611

2626-
2627-
26282612
/*
2629-
* Allocate and return a SLICE object, which will contain the appropriate coordinate and length information for
2630-
* accessing some part of a matrix.
2613+
* Modify an existing SLICE object (with properly allocated memory),
2614+
* so that it will contain the appropriate coordinate and length information
2615+
* for accessing some part of a matrix.
26312616
*/
2632-
static SLICE* get_slice(size_t dim, int argc, VALUE* arg, size_t* shape) {
2617+
static void init_slice_no_alloc(SLICE* slice, size_t dim, int argc, VALUE* arg, size_t* shape) {
26332618
NM_CONSERVATIVE(nm_register_values(arg, argc));
26342619

26352620
VALUE beg, end;
26362621
int excl;
26372622

2638-
SLICE* slice = alloc_slice(dim);
26392623
slice->single = true;
26402624

26412625
// r is the shape position; t is the slice position. They may differ when we're dealing with a
@@ -2693,7 +2677,6 @@ static SLICE* get_slice(size_t dim, int argc, VALUE* arg, size_t* shape) {
26932677
}
26942678

26952679
NM_CONSERVATIVE(nm_unregister_values(arg, argc));
2696-
return slice;
26972680
}
26982681

26992682
#ifdef BENCHMARK

0 commit comments

Comments
 (0)