Tutorial 3: How to Add Tensor Ordering

SparseViz allows its users to add the custom tensor orderings that they want to implement on their tensors. Adding such tensor orderings into SparseViz involves a couple of elementary steps. In this tutorial, these steps are going to be explained in a detailed manner.

Every custom tensor ordering in the SparseViz ecosystem derives from the abstract TensorOrdering class. SparseViz/include/Tensor/Orderings is where the header file of this custom ordering class could be created and SparseViz/src/Tensor/Orderings is where the source file of this custom ordering class could be created. In this tutorial, we are going to create an example tensor ordering named AddingTensorOrdering and show how it can be integrated into the library.

Step 1: Creating a Custom Ordering Class

First, we will create the AddingTensorOrdering.h file in the SparseViz/include/Tensor/Orderings directory.

The header file will contain the declaration of our class, which consists of only 5 lines of C++ code.

AddingTensorOrdering.h

#include "TensorOrdering.h"

class AddingTensorOrdering: public TensorOrdering

{

    public:

    AddingTensorOrdering (SparseTensor& tensor, const std::vector\<vType\>& active_modes, std::string orderingName, std::string orderingParameters);

    virtual void orderingFunction() override;

};

TensorOrdering has only one pure virtual function that it dictates to be overridden by every derived class. This function is called orderingFunction which would carry the implementation of the ordering logic. In addition to that, a constructor should be written for the custom tensor ordering classes whose first 3 parameters have to be the reference to the tensor on which the ordering will be applied, the active modes of the tensor, and the name of the ordering, respectively. The fourth parameter is optional in that it can be skipped safely if the custom order does not need any parameters to work properly.

Having declared our class, next is to create its source file named AddingTensorOrdering.cpp under the directory SparseViz/src/Tensor/Orderings.

AddingTensorOrdering.cpp

#include "AddingTensorOrdering.h"

AddingTensorOrdering:: AddingTensorOrdering (SparseTensor &tensor, const std::vector<vType>& active_modes, std::string orderingName, std::string orderingParameters)
:   TensorOrdering(tensor, active_modes, orderingName, 5)

{

    // Ordering parameters could be parsed (remember the delimiter is '/')

    // and appropriate private member variables could be set here

}

void AddingTensorOrdering::orderingFunction()

{

    vType tensorOrder = this->getTensor().getOrder();

    orderedDimensions = new vType*[tensorOrder];

    for (int i = 0; i != tensorOrder; ++i)

    {

        orderedDimensions[i] = new vType[dims[i]];

    }

    // Your ordering function logic goes here

}

There are a couple of important parts in the source code that require careful attention. The first is the initialization of the base class TensorOrdering in the constructor of the AddingTensorOrdering class. TensorOrdering expects the following parameters to be provided.

SparseTensor& tensor

const std::vector& active_modes

std::string orderingName

unsigned int orderingFunctionPrice = 0

The first 3 parameters, matrix, active_modes, and orderingName, could easily be provided to the parent class with the constructor parameters of the child class. The last parameter is an integer between 0 to 10 representing the overhead of the ordering function. Although it has a default value of 0, we recommend custom ordering derived classes to specify this value, as appropriate values could increase the performance of the program. For our ordering class, we will assume that it has an orderingFunction overhead value of 5.

The last important remark that we need to make is that in the custom tensor orderings, a matrix should be generated by the orderingFunction. This matrix is a protected member variable of TensorOrdering called orderedDimensions that would keep track of the new locations of each dimension after the ordering is implemented. This matrix should be allocated on the heap as shown in the above code snippet. The custom tensor ordering class is not responsible for deleting this matrix, as the base TensorOrdering class will safely handle this.

Step 2: Adding Files into CMakeLists.txt

In the former step, we created our header file and source file for our class named AddingTensorOrdering. In this step, we are going to include these files in our build automation tool. SparseViz utilizes CMake as its build system. In the CMakeLists.txt file located under the project directory, we should include our header file under the HEADER_FILES environment variable and include our source under the SOURCE_FILES environment variable, like so:

CMakeLists.txt

set(HEADER_FILES

    --- OTHER HEADER FILES (CROPPED) ---

    include/Tensor/Orderings/AddingTensorOrdering.h

)

set(SOURCE_FILES

    --- OTHER SOURCE FILES (CROPPED) ---

    src/Tensor/Orderings/AddingTensorOrdering.cpp

)

Step 3: Adding Ordering Definition Into SparseVizEngine

As the last step, we are going to add our ordering class definition into SparseVizEngine and allow the library to identify the presence of this ordering. As our first job, we are going to include our custom ordering class' header file into the SparseVizEngine.h:

SparseVizEngine.h

#include "AddingTensorOrdering.h"

After that, we are going to add the definition of the class to the tensor ordering factory function located in the source file of the SparseVizEngine

SparseVizEngine.cpp

TensorOrdering *SparseVizEngine::tensorOrderingFactory(SparseTensor&tensor, const std::vector<vType>& active_modes, std::string orderingClassName, std::string orderingName, std::string orderingParameters)

{

    --- OTHER ORDERING CLASSES (CROPPED) ---

    else if (orderingClassName == "AddingTensorOrdering")

    {

        return new AddingTensorOrdering(tensor, active_modes, orderingName, orderingParameters);

    }

    return nullptr;

}

Having done this, we can easily run this ordering from within the config file by indicating it under the section *TENSOR_ORDERINGS*, like so:

config

*TENSOR_ORDERINGS*

AddingTensorOrdering | WeHaveAddedATensorOrdering | Param1/Param2/Param3

This concludes tutorial 3, the way to add tensor orderings into the library.