tuple

Applicability

Product

Supported

Atlas A3 training products/Atlas A3 inference products

Atlas A2 training products/Atlas A2 inference products

Atlas 200I/500 A2 inference products

x

Atlas inference product's AI Core

x

Atlas inference product's Vector Core

x

Atlas training products

x

Function

In C++, tuple is a powerful container that allows to store multiple elements of different types. It can be used in the following scenarios:

  • When a function needs to return multiple values of different types, tuple is a great option. It prevents creating a structure or class to encapsulate multiple return values, especially when you do not need to create separate types for these return values.
  • When you need to store data of different types, you can use tuple to store heterogeneous elements. For example, the query result of stored data contains fields of different types.
  • In function calls, if you need to pass multiple parameters of different types but do not want to create a structure for them, you can use tuple to group these parameters.
  • In template metaprogramming, tuple can be used as a type list to store multiple types of information.
  • When the program needs to store and transfer multiple status information in different phases, tuple can be used to store the status information in a unified manner for easy management.
  • In some generic algorithms, tuple can be used to store computing results or intermediate results.
  • In template metaprogramming, tuple can be used to store and expand parameter packages.

The following describes the tuple constructors:

  • Default constructor: creates an empty tuple.
  • Initialization list constructor: provides the element values when an object is created.
  • Copy constructor: copies an existing tuple.

In addition, Ascend C provides the make_tuple function to create a tuple. This function can automatically infer the element type, making the code more concise. You can also use make_tuple to construct an element list.

Prototype

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
template <typename Tp, typename ...Tps>
class tuple<Tp, Tps...> : public tuple<Tps...> 
{
public:
    __aicore__ inline tuple();

    __aicore__ inline tuple(const Tp& val, const Tps& ...params);

    __aicore__ inline tuple(Tp&& val, Tps&& ...params);

    template <typename Head, typename ...Args>
    __aicore__ inline tuple<Tp, Tps...>& operator=(const tuple<Head, Args...>& t);
}

Parameters

Table 1 Template parameters

Parameter

Description

Tps...

Parameter package of the input type. The number of parameters ranges from 0 to 64.

For the Atlas A3 training products/Atlas A3 inference products, the supported data types are bool, int4b_t, int8_t, uint8_t, int16_t, uint16_t, half, bfloat16_t, int32_t, uint32_t, float, int64_t, uint64_t, LocalTensor and GlobalTensor.

For the Atlas A2 training products/Atlas A2 inference products, the supported data types are bool, int4b_t, int8_t, uint8_t, int16_t, uint16_t, half, bfloat16_t, int32_t, uint32_t, float, int64_t, uint64_t, LocalTensor and GlobalTensor.

Restrictions

  • The tuple instantiation depth is 64, that is, aggregation of data types with a maximum of 64 elements is supported.
  • If the constructor is an initialization list, data in the list must be left values or right values. The number and types of elements in the initialization list must strictly match those defined by tuple.
  • Variable-length data types such as arrays are not supported.
  • Implicit conversion constructors are not supported.
  • Currently, tuples are implemented based on inheritance. For example, the tuple<int, int> a =make_tuple(1, 2, 3) statement will trigger implicit conversion. In addition, due to the C++ object slice feature, redundant data will be discarded. Therefore, you are advised not to use the preceding statement.

Returns

None

Example

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
AscendC::LocalTensor<T> src0Local = inQueueX.AllocTensor<T>();
AscendC::LocalTensor<T> src1Local = inQueueX2.AllocTensor<T>();

// make_tuple aggregates the tensor structure.
auto testMakeTensor = AscendC::Std::make_tuple(src0Local, src1Local, src0_global, src1_global);

AscendC::PRINTF("tuple size is --> %d\n", AscendC::Std::tuple_size<decltype(testMakeTensor)>::value);

// Initialize aggregation of the list constructor.
AscendC::Std::tuple<AscendC::LocalTensor<T>, AscendC::LocalTensor<T>, AscendC::GlobalTensor<T>, AscendC::GlobalTensor<T>> testTensor{src0Local, src1Local, src0_global, src1_global};

// Copy the construction mode.
AscendC::Std::tuple<AscendC::LocalTensor<T>, AscendC::LocalTensor<T>, AscendC::GlobalTensor<T>, AscendC::GlobalTensor<T>> test2Tensor = testTensor;

AscendC::Std::tuple<AscendC::LocalTensor<T>, AscendC::LocalTensor<T>, AscendC::GlobalTensor<T>, AscendC::GlobalTensor<T>> test3Tensor;

// Operator overloading
test3Tensor = test2Tensor;

AscendC::PRINTF("tuple size is --> %d\n", AscendC::Std::tuple_size<decltype(test3Tensor)>::value);

// Use the get method to obtain the corresponding element.
AscendC::LocalTensor<T> src0LocalTuple = AscendC::Std::get<0>(test3Tensor);
AscendC::LocalTensor<T> src1LocalTuple = AscendC::Std::get<1>(test3Tensor);

AscendC::GlobalTensor<T> src0_globalTuple = AscendC::Std::get<2>(test3Tensor);
AscendC::GlobalTensor<T> src1_globalTuple = AscendC::Std::get<3>(test3Tensor);        

// Aggregate the initialization lists of multiple data types.
AscendC::Std::tuple<AscendC::int4b_t, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, uint64_t, int64_t, half, float, \
bfloat16_t, fp8_e8m0_t, bool> test1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10.0, 11.0, 12.0, 13.0, true};

AscendC::PRINTF("tuple size is --> %d\n", AscendC::Std::tuple_size<decltype(test1)>::value);

// Use the get method to obtain elements of multiple data types.
AscendC::int4b_t        number_int4b_t =        AscendC::Std::get<0>(test1);
int8_t                  number_int8_t =         AscendC::Std::get<1>(test1);
uint8_t                 number_uint8_t =        AscendC::Std::get<2>(test1);
int16_t                 number_int16_t =        AscendC::Std::get<3>(test1);
uint16_t                number_uint16_t =       AscendC::Std::get<4>(test1);
int32_t                 number_int32_t =        AscendC::Std::get<5>(test1);
uint32_t                number_uint32_t =       AscendC::Std::get<6>(test1);
uint64_t                number_uint64_t =       AscendC::Std::get<7>(test1);
int64_t                 number_int64_t =        AscendC::Std::get<8>(test1);
half                    number_half =           AscendC::Std::get<9>(test1);
float                   number_float =          AscendC::Std::get<10>(test1);
bfloat16_t              number_bfloat16_t =     AscendC::Std::get<11>(test1);
fp8_e8m0_t              number_fp8_e8m0_t =     AscendC::Std::get<12>(test1);
bool                    number_bool =           AscendC::Std::get<13>(test1);

// Use the get method to obtain the element reference and continue the computation.
AscendC::Std::get<1>(test1)+= 1 ;
AscendC::Std::get<2>(test1)+= 1 ;
AscendC::Std::get<3>(test1)+= 1 ;
AscendC::Std::get<4>(test1)+= 1 ;
AscendC::Std::get<5>(test1)+= 1 ;
AscendC::Std::get<6>(test1)+= 1 ;
AscendC::Std::get<7>(test1)+= 1 ;
AscendC::Std::get<8>(test1)+= 1 ;
AscendC::Std::get<10>(test1) += (float)1.0 ;

// Use make_tuple to initialize data types of fixed elements in the list.
auto test2 = AscendC::Std::make_tuple(AscendC::int4b_t (1) ,int8_t (2) ,uint8_t (3) ,int16_t (4) ,uint16_t (5) ,int32_t (6) , \
    uint32_t (7) ,uint64_t (8) ,int64_t (9) ,half (10) ,float (11) ,bfloat16_t (12) ,fp8_e8m0_t (13) , bool (true));

AscendC::PRINTF("tuple size is --> %d\n", AscendC::Std::tuple_size<decltype(test2)>::value);

// Use the get method to obtain elements of multiple data types.
number_int4b_t =        AscendC::Std::get<0>(test2);
number_int8_t =         AscendC::Std::get<1>(test2);
number_uint8_t =        AscendC::Std::get<2>(test2);
number_int16_t =        AscendC::Std::get<3>(test2);
number_uint16_t =       AscendC::Std::get<4>(test2);
number_int32_t =        AscendC::Std::get<5>(test2);
number_uint32_t =       AscendC::Std::get<6>(test2);
number_uint64_t =       AscendC::Std::get<7>(test2);
number_int64_t =        AscendC::Std::get<8>(test2);
number_half =           AscendC::Std::get<9>(test2);
number_float =          AscendC::Std::get<10>(test2);
number_bfloat16_t =     AscendC::Std::get<11>(test2);
number_fp8_e8m0_t =     AscendC::Std::get<12>(test2);
number_bool =           AscendC::Std::get<13>(test2);

// Use the get method to obtain the element reference and continue the computation.
AscendC::Std::get<1>(test2)+= 1 ;
AscendC::Std::get<2>(test2)+= 1 ;
AscendC::Std::get<3>(test2)+= 1 ;
AscendC::Std::get<4>(test2)+= 1 ;
AscendC::Std::get<5>(test2)+= 1 ;
AscendC::Std::get<6>(test2)+= 1 ;
AscendC::Std::get<7>(test2)+= 1 ;
AscendC::Std::get<8>(test2)+= 1 ;
AscendC::Std::get<10>(test2) += (float)1.0 ;

// Aggregate the variable initialization list.
AscendC::Std::tuple<AscendC::int4b_t, int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, uint64_t, int64_t, half, float, \
bfloat16_t, fp8_e8m0_t, bool> test3 = {
    number_int4b_t, number_int8_t, number_uint8_t, number_int16_t, number_uint16_t, number_int32_t, number_uint32_t, \
    number_uint64_t, number_int64_t, number_half, number_float, number_bfloat16_t, number_fp8_e8m0_t, number_bool, 
};

AscendC::PRINTF("tuple size is --> %d\n", AscendC::Std::tuple_size<decltype(test3)>::value);

uint32_t const_uint32_t = 0;
float const_float = 0.0;
bool const_bool = false;

// Constant type
const AscendC::Std::tuple<uint32_t, float, bool> test4{11, 2.2, true};

// Use the get method to obtain the constant type.
const_uint32_t = AscendC::Std::get<0>(test4);
const_float = AscendC::Std::get<1>(test4);
const_bool = AscendC::Std::get<2>(test4);

AscendC::Std::tuple_element<0,decltype(test4)>::type first = 77;
AscendC::Std::tuple_element<1,decltype(test4)>::type second = 7.7;
AscendC::Std::tuple_element<2,decltype(test4)>::type third = false;

AscendC::PRINTF("The value of the test element is: %d, %f, %d\n", first, second, third);

AscendC::Std::tie(const_uint32_t, const_float, const_bool) = test4;

AscendC::PRINTF("The value of the test element is: %d, %f, %d\n", const_uint32_t, const_float, const_bool);

// Aggregate const elements.
AscendC::Std::tuple<const uint32_t, const float, const bool> test5{33, 4.4, true};

// Use the get method to obtain const elements.
const_uint32_t = AscendC::Std::get<0>(test5);
const_float = AscendC::Std::get<1>(test5);
const_bool = AscendC::Std::get<2>(test5);

const AscendC::Std::tuple<const uint32_t, const float, const bool> test6{33, 4.4, true};

const_uint32_t = AscendC::Std::get<0>(test6);
const_float = AscendC::Std::get<1>(test6);
const_bool = AscendC::Std::get<2>(test6);

// Initialize the default construction.
AscendC::Std::tuple<\
uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, \
uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, \
uint32_t, uint32_t, uint32_t, uint8_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t,\
uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, \
uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, \
uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, \
uint32_t, uint32_t, uint32_t, uint32_t> test7;

// Initialize aggregation of default elements.
auto test8 = AscendC::Std::make_tuple(\
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, \
    11, 12, 13, 14, 15, 16, 17, 18, 19, 20, \
    21, 22, 23, 24, 25, 26, 27, 28, 29, 30, \
    31, 32, 33, 34, 35, 36, 37, 38, 39, 40, \
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, \
    51, 52, 53, 54, 55, 56, 57, 58, 59, 60, \
    61, 62, 63, 64);

// Overload the assignment operator.
test7 = test8;

AscendC::PRINTF("tuple size is --> %d\n", AscendC::Std::tuple_size<decltype(test7)>::value);
AscendC::PRINTF("tuple size is --> %d\n", AscendC::Std::tuple_size<decltype(test8)>::value);

// Use make_tuple to initialize initialization.
AscendC::Std::tuple<uint32_t, float, bool> test9 = AscendC::Std::make_tuple(const_uint32_t, const_float, const_bool);

const_uint32_t = AscendC::Std::get<0>(test9);
const_float = AscendC::Std::get<1>(test9);
const_bool = AscendC::Std::get<2>(test9);

AscendC::PRINTF("tuple size is --> %d\n", AscendC::Std::tuple_size<decltype(test9)>::value);

using Element0Type = AscendC::Std::tuple_element<0, decltype(test9)>::type;
Element0Type element0 = 88;

using Element1Type = AscendC::Std::tuple_element<1, decltype(test9)>::type;
Element1Type element1 = 8.8;

using Element2Type = AscendC::Std::tuple_element<2, decltype(test9)>::type;
Element2Type element2 = true;

AscendC::PRINTF("The value of the test element is: %d, %f, %d\n", element0, element1, element2);

AscendC::Std::tie(const_uint32_t, const_float, const_bool) = test9;

AscendC::PRINTF("The value of the test element is: %d, %f, %d\n", const_uint32_t, const_float, const_bool);
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// Execution result:
(testMakeTensor) tuple size is --> 4
(test3Tensor) tuple size is --> 4
(test1) tuple size is --> 14
(test2) tuple size is --> 14
(test3) tuple size is --> 14
(test4 tuple_element) The value of the test element is: 77, 7.700000, 0
(test4 tie) The value of the test element is: 11, 2.200000, 1
(test7) tuple size is --> 64
(test8) tuple size is --> 64
(test9) tuple size is --> 3
(test9 tuple_element) The value of the test element is: 88, 8.800000, 1
(test9 tie) The value of the test element is: 33, 4.400000, 1