KIDS  ver-0.0.1
KIDS : Kernel Integrated Dynamics Simulator
Loading...
Searching...
No Matches
Einsum.h File Reference

this file provides einsum operation More...

#include <cstring>
#include <string>
#include <vector>
Include dependency graph for Einsum.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  PROJECT_NS::EinsumIdx
 EinsumIdx is a struct store information of index used in einsum operation. More...
 
struct  PROJECT_NS::DimenHelper
 DimenHelper is a struct control dimensional utils on the orginal/einsum index for a given tensor. More...
 
class  PROJECT_NS::EinsumHelper
 

Namespaces

namespace  PROJECT_NS
 < http://warp.povusers.org/FunctionParser/fparser.html
 

Functions

template<typename T >
void PROJECT_NS::einsum (EinsumHelper &EH, const std::vector< T * > &data_inputs, T *data_output)
 
template<typename T >
void PROJECT_NS::einsum (const std::string &einsum_expression, std::vector< T * > data_inputs, const std::vector< std::vector< std::size_t > > &shape_inputs, T *data_output, const std::vector< std::size_t > &shape_output={})
 

Detailed Description

this file provides einsum operation

About the rules in einsum operations provided by "einsum.h"

In this documentation, we define key terms related to the einsum operation:

  • einsum label: Refers to the labels assigned to the indices of the operands involved in the einsum operation. For example, 'a', 'b', 'c' could be operand labels.
  • einsum shape: Describes the shape or dimensions of a tensor corresponding to each operand. For instance, "abc" could represent the shape of a tensor.
  • einsum expression: Specifies the einsum operation to be performed, indicating the contraction pattern of indices between operands. For example, "ab,bc->ac" defines how the indices from two operands are contracted to produce the final output.

einsum label:

  • fixed label: expressed as [name]. It cannot appear in user's deduction!
  • inner label: appeared in user's deduction or only appears once in summation.
  • outer label: not in user's deduction or appears multiple times in summation.

rules for einsum expression:

  • user's deduction: -> indicates for einsum result. Then all (non-fixed) labels appear behind -> are treated as outer labels, while those not appear behind -> are used as inner labels.
  • automatic deduction: if -> is not provided in einsum expression. The inner/ outer labels are seperated by the times they appear in summation.

Declaration

This file provides a einsum operation with an easy realization, the performance is not optimized so well. Based on some test, there are about 20x slower than in optimized loop in pure C.

benckmark cases

the following benchmark test is passed:

std::size_t L = 2 * 2 * 2 * 2 * 3 * 3 * 3 * 3;
std::vector<int> A(L, 0);
for (int z = 0; z < L; ++z) {
A[z] = z % 3 - (z % 5) * (z % 5) + (z % 7);
}
std::vector<int> res(L, 0);
einsum("i", {A.data()}, {{L}}, res.data(), {L});
ARRAY_SHOW(res.data(), 1, 1);
einsum("i->", {A.data()}, {{L}}, res.data(), {1});
ARRAY_SHOW(res.data(), 1, 1);
einsum("ikkkji->j", {A.data()}, {{2, 3, 3, 3, 12, 2}}, res.data(), {12});
ARRAY_SHOW(res.data(), 1, 12);
einsum("ikkkji->ik", {A.data()}, {{2, 3, 3, 3, 12, 2}}, res.data(), {2, 3});
ARRAY_SHOW(res.data(), 2, 3);
einsum("i,i", {A.data(), A.data()}, {{L}, {L}}, res.data(), {1});
ARRAY_SHOW(res.data(), 1, 1);
einsum("ik,ik", {A.data(), A.data()}, {{16, 81}, {16, 81}}, res.data(), {1});
ARRAY_SHOW(res.data(), 1, 1);
einsum("ik,ki", {A.data(), A.data()}, {{16, 81}, {81, 16}}, res.data(), {1});
ARRAY_SHOW(res.data(), 1, 1);
einsum("ik,kj->ij", {A.data(), A.data()}, {{4, 324}, {324, 4}},
res.data(), {4, 4});
ARRAY_SHOW(res.data(), 4, 4);
einsum("ik,kj,ljjlll->il", {A.data(), A.data(), A.data()},
{{4, 324}, {324, 4}, {3, 4, 4, 3, 3, 3}},
res.data(), {4, 3});
ARRAY_SHOW(res.data(), 4, 3);
#define ARRAY_SHOW(_A, _n1, _n2)
Definition array_utils.h:54
void einsum(EinsumHelper &EH, const std::vector< T * > &data_inputs, T *data_output)
Definition Einsum.h:219
int A
Definition conv_xyz.py:18

which is coincided with the results by numpy's einsum() function:

import numpy as np
L = 2*2*2*2*3*3*3*3
z = np.arange(L)
A = (z%3) - (z%5)**2 + (z%7)
print(np.einsum('i', A))
print(np.einsum('i->', A))
print(np.einsum('ikkkji->j', A.reshape((2,3,3,3,12,2))))
print(np.einsum('ikkkji->ik', A.reshape((2,3,3,3,12,2))))
print(np.einsum('i,i', A, A))
print(np.einsum('ik,ik', A.reshape((16,81)), A.reshape((16,81))))
print(np.einsum('ik,ki', A.reshape((16,81)), A.reshape((81,16))))
print(np.einsum('ik,kj->ij', A.reshape((4,324)), A.reshape((324,4))))
print(np.einsum('ik,kj,ljjlll->il', A.reshape((4,324)),
A.reshape((324,4)), A.reshape((3,4,4,3,3,3))))

the results are:

[ 0 1 0 ... -4 -9 2]
-2589
[-25 -9 -9 -8 -11 -22 -8 -15 -5 -10 -21 -5]
[[-18 -28 -33]
[-27 -21 -21]]
56293
56293
52891
[[-2724 3071 8230 7447]
[-8259 -3074 3047 8535]
[ 6290 -8694 -3109 3442]
[ 8340 6031 -8557 -2810]]
[[ 83744 54125 79687]
[ 57250 -22579 -1748]
[ -9172 -21858 -39479]
[-39026 55563 -10344]]
Author
Xin He
Date
2024-03
Version
1.0
[logs]:
Date Description
2024-03-29 initial version. The shape_inputs and shape_output are consistent with that interface Basic_Shape in the file Shape.h.

Definition in file Einsum.h.