Skip to content

Slice and Subtensor

amitsingh19975 edited this page Aug 23, 2019 · 8 revisions

Introduction

A slice object is used to specify how to slice extents. You can specify where to start the slicing, and where to end. You can also specify the step. My implementation contains two types of slice, one is static and another one is dynamic. The static one is a compiled time object which is decreases runtime cost compared to the dynamic slice.

A subtensor object is used to create new tensor without copying or moving old tensor data which needs new memory space and increases runtime cost. For example, you need to do some tensor operation inside a loop by creating a new tensor again and again by copying the tensor which inturns increase the runtime. If we use subtensor runtime cost decreases drastically.

Subtensor reduces this runtime cost by taking the pointer to the tensor data, which is cheap to copy.

Slice

I took the slice implementation from Cem Bassoy's previous year's implementation of span and created the improved one from the ground up and added the concept of a static slice and a dynamic slice.

Current slice vs Old slice

  1. I have combined both stridden and sliced slice as the previous one used the tag to identify them.
  2. Added static and dynamic concept and there is no such concept in the previous one.
  3. Removed two functions which were not begin used ( operator[] for getting the position and operator() for getting new slice after passing old slice )
  4. No concept of ran function

Missing Feature

  1. Reverse iterating when step is < 0
using namespace boost::numeric::ublas;

// can be both static or dynamic based the situation but by default, it's treated as dynamic
auto s1 = span::slice<>{}; 

// dynamic slice ( start: 0, end: 10, step: 1 )
auto s2 = span::slice<>{0,10};

// dynamic slice ( start: 0, end: 10, step: 4 )
auto s3 = span::slice<>{0,10,4};

// dynamic slice ( start: 0, end: ( extent - 2 ), step: 4 )
auto s4 = span::slice<>{0,-2,4}; 

// dynamic slice ( start: ( extent - 7 ), end: ( extent - 2 ), step: 4 )
// caution: if both numbers are negative then start must be less than end ( -7 < -3 or start < end )
auto s5 = span::slice<>{-7,-2,4}; 

// dynamic slice ( start: 3, end: 3, step: 1 )
auto s6 = span::slice<>{3}; 

// dynamic slice ( start: ( extent - 3 ), end: ( extent - 3 ), step: 1 )
auto s7 = span::slice<>{-3};

// dynamic slice ( start: ( extent - 3 ), end: 8, step: 1 )
// caution: (extent - 3) < 8
auto s8 = span::slice<>{-3, 8}; 
 
// static slice ( start: 0, end: 10, step: 1 )
auto s9 = span::slice<0,10>{};

// static slice ( start: 0, end: 10, step: 4 )
auto s10 = span::slice<0,10,4>{};

// static slice ( start: 0, end: ( extent - 2 ), step: 4 )
auto s11 = span::slice<0,-2,4>{}; 

// static slice ( start: ( extent - 7 ), end: ( extent - 2 ), step: 4 )
// caution: if both numbers are negative then start must be less than end ( -7 < -3 or start < end )
auto s12 = span::slice<-7,-2,4>{};

// static slice ( start: 3, end: 3, step: 1 )
auto s13 = span::slice<3>{}; 

// static slice ( start: ( extent - 3 ), end: ( extent - 3 ), step: 1 )
auto s14 = span::slice<-3>{};

// static slice ( start: ( extent - 3 ), end: 8, step: 1 )
// caution: (extent - 3) < 8
auto s15 = span::slice<-3, 8>{}; 

Customizing Slice

boost::numeric::ublas::span::slice<> is type alias for boost::numeric::ublas::basic_slice<ptrdiff_t,Args...> so for some reason you want to use different type for slice.

template<ptrdiff_t,... Args>
using my_slice = boost::numeric::ublas::basic_slice<size_t,Args...>;

auto s1 = my_slice<0,6,3>{};

Subtensor

Similar to slice I took the implementation from subtensor and added the support for both the static slice and the dynamic slice.

I also modified the subtensor helper functions which needed to be modified for the static slice and dynamic slice. Now if tensor has static extents and static slice, the type of subtensor will be static subtensor and other this condition subtensor is dynamic subtensor.

Missing Features

  1. It is missing a few functions such as data, rank, etc
  2. Better support for the tensor operation
using namespace boost::numeric::ublas;
auto t1 = tensor{static_extents<10,10>{},1.f};
auto t2 = tensor{dynamic_extents<>{10,10},1.f};

//static subtensor
auto s1 = t1(span::slice<2,3>{}, span::slice<>{}};

//dynamic subtensor
auto s2 = t1(span::slice<>{2,3}, span::slice<>{}};

//dynamic subtensor
auto s3 = t2(span::slice<>{2,3}, span::slice<>{}};

/-----------other ways to create subtensor---------------/

// static subtensor
auto s4 = subtensor<decltype(t1),span::slice<0,5>,span::slice<4>>{ t1 };

// dynamic subtensor
auto s5 = subtensor{ t1, ,span::slice<>{0,5},span::slice<>{4} };

Future scope

I will try to mitigate all the problems which are discussed above, after mitigating I will implement reverse iterating when step < 0 and I am thinking of adding python like slice using string. This slice using string will reduce writing slice again and again as it will follow DRY( Do not Repeat Yourself ).

Clone this wiki locally