Dynamic Shapes¶
For an example on how to use dynamic shapes, see the Scenario Two: Known Partial Shape documentation.
Runtime Error Checking¶
Static typechecking in the presence of dynamic shapes will make optimistic
assumptions about things like shape mismatches. For example, if an elementwise
op is provided inputs of shapes (2,?)
and (?,5)
, the type checker will
proceed under the assumption that the user is not going to pass tensors with
inconsistent shape at runtime, and therefore infer an output shape of (2,5)
.
That means that shape mismatches can now occur at runtime.
PartialShape, Dimension, and Rank Classes¶
Partial shape information is expressed via the PartialShape
, Dimension
,
and Rank
classes.
Note
Rank
is an alias for Dimension
, used when the value represents
the number of axes in a shape, rather than the size of one dimension in a shape.

class
PartialShape
¶ Class representing a shape that may be partially or totally dynamic.
XXX: THIS CLASS IS EXPERIMENTAL AND THE ENTIRE DESIGN IS SUBJECT TO CHANGE.
A PartialShape may have:
 Dynamic rank. (Informal notation:
?
)  Static rank, but dynamic dimensions on some or all axes. (Informal notation examples:
{1,2,?,4}
,{?,?,?}
)  Static rank, and static dimensions on all axes. (Informal notation examples:
{1,2,3,4}
,{6}
,{}
)
Public Functions

PartialShape
(std::initializer_list<Dimension> init)¶ Constructs a shape with static rank from an initializer list of Dimension.
Examples:
 Parameters
init
: The Dimension values for the constructed shape.
PartialShape s{2,3,4}; // rank=3, all dimensions static PartialShape s{}; // rank=0 PartialShape s{2,Dimension::dynamic(),3}; // rank=3, dimension 1 dynamic

PartialShape
(const std::vector<Dimension> &dimensions)¶ Constructs a PartialShape with static rank from a vector of Dimension.
 Parameters
dimensions
: The Dimension values for the constructed shape.

PartialShape
()¶ Constructs a static PartialShape with zero rank (the shape of a scalar).

PartialShape
(const Shape &shape)¶ Constructs a static PartialShape from a Shape.
 Parameters
shape
: The Shape to convert into PartialShape.

bool
is_static
() const¶ Check if this shape is static.
A shape is considered static if it has static rank, and all dimensions of the shape are static.
 Return
true
if this shape is static, elsefalse
.

bool
is_dynamic
() const¶ Check if this shape is dynamic.
A shape is considered static if it has static rank, and all dimensions of the shape are static.
 Return
false
if this shape is static, elsetrue
.

Rank
rank
() const¶ Get the rank of the shape.
 Return
 The rank of the shape. This will be Rank::dynamic() if the rank of the shape is dynamic.

bool
compatible
(const PartialShape &s) const¶ Check whether this shape is compatible with the argument, i.e., whether it is possible to merge them.
Two shapes are compatible if
 one or both of them has dynamic rank, or
 both shapes have dynamic and equal rank, and their dimensions are elementwise compatible (see Dimension::compatible()).
 Return
true
if this shape is compatible withs
, elsefalse
. Parameters
s
: The shape to be checked for compatibility with this shape.

bool
same_scheme
(const PartialShape &s) const¶ Check whether this shape represents the same scheme as the argument.
Two shapes
s1
ands2
represent the same scheme if they both have dynamic rank, or
 they both have static and equal rank
r
, and for everyi
from0
tor1
,s1[i]
represents the same scheme ass2[i]
(see Dimension::same_scheme()).
 Return
true
if this shape represents the same scheme ass
, elsefalse
. Parameters
s
: The shape whose scheme is being compared with this shape.

bool
relaxes
(const PartialShape &s) const¶ Check whether this shape is a relaxation of the argument.
Intuitively, a
PartialShapes1
is said to relaxs2
(or is a relaxation ofs2
) if it is “more permissive” thans2
. In other words,s1
is a relaxation ofs2
if anything you can form by plugging things into the dynamic dimensions ofs2
is also something you can form by plugging things into the dynamic dimensions ofs1
, but not necessarily the other way around. Return
true
if this shape relaxess
, elsefalse
. Parameters
s
: The shape which is being compared against this shape.
s1.relaxes(s2)
is equivalent tos2.refines(s1)
.Formally, PartialShape
s1
is said to relax PartialShapes2
if:s1
has dynamic rank, ors1
ands2
both have static rankr
, and for everyi
from0
tor1
, eithers1[i]
is dynamic, ors1[i]
==s2[i]
.

bool
refines
(const PartialShape &s) const¶ Check whether this shape is a refinement of the argument.
Intuitively, a
PartialShapes1
is said to relaxs2
(or is a relaxation ofs2
) if it is “less permissive” thans2
. In other words,s1
is a relaxation ofs2
if anything you can form by plugging things into the dynamic dimensions ofs1
is also something you can form by plugging things into the dynamic dimensions ofs2
, but not necessarily the other way around. Return
true
if this shape refiness
, elsefalse
. Parameters
s
: The shape which is being compared against this shape.
s1.refines(s2)
is equivalent tos2.relaxes(s1)
.Formally, PartialShape
s1
is said to refine PartialShapes2
if:s2
has dynamic rank, ors1
ands2
both have static rankr
, and for everyi
from0
tor1
, eithers2[i]
is dynamic, ors1[i]
==s2[i]
.

bool
merge_rank
(Rank r)¶ Checks that this shape’s rank is compatible with
r
, and, if this shape’s rank is dynamic andr
is static, updates this shape to have a rank ofr
with dimensions all dynamic. Return
true
if this shape’s rank is compatible withr
, elsefalse
.

Shape
to_shape
() const¶ Convert a static PartialShape to a Shape.
 Return
 A new Shape
s
wheres[i] = size_t((*this)[i])
.  Exceptions
std::invalid_argument
: If this PartialShape is dynamic.

bool
all_non_negative
() const¶ Returns
true
if all static dimensions of the tensor are nonnegative, elsefalse
.

const Dimension &
operator[]
(size_t i) const¶ Index operator for PartialShape.
 Return
 A reference to the
i
th Dimension of this shape.  Parameters
i
: The index of the dimension being selected.

Dimension &
operator[]
(size_t i)¶ Index operator for PartialShape.
 Return
 A reference to the
i
th Dimension of this shape.  Parameters
i
: The index of the dimension being selected.

operator std::vector<Dimension>
() const¶ Returns a vector of the dimensions. This has no meaning if dynamic.
Public Static Functions

PartialShape
dynamic
(Rank r = Rank::dynamic())¶ Construct a PartialShape with the given rank and all dimensions (if any) dynamic.
 Return
 A PartialShape with the given rank, and all dimensions (if any) dynamic.

bool
merge_into
(PartialShape &dst, const PartialShape &src)¶ Try to merge one shape into another.
Merges
src
intodst
, returningtrue
on success andfalse
on failure. Iffalse
is returned, the effect ondst
is unspecified. Return
true
if merging succeeds, elsefalse
. Parameters
dst
: The shape thatsrc
will be merged into.src
: The shape that will be merged intodst
.
To merge two partial shapes
s1
ands2
is to find the most permissive partial shapes
that is no more permissive thans1
ors2
, ifs
exists. For example:merge(?,?) > ? merge(?,{?,?}) > {?,?} merge({?,?},{?,?}) > {?,?} merge({1,2,3,4},?) > {1,2,3,4} merge({1,2},{1,?}) > {1,2} merge({1,2,?,?},{1,?,3,?}) > {1,2,3,?} merge({1,2,3},{1,2,3}) > {1,2,3} merge({1,?},{2,?}) fails [dimension 0 constraints are inconsistent] merge({?,?},{?,?,?}) fails [ranks are inconsistent]
This function (merge_into) performs the “merge” operation described above on
dst
andsrc
, but overwritesdst
with the result and returnstrue
if merging is successful; if merging is unsuccessful, the function returnsfalse
and may make unspecified changes todst
.

bool
broadcast_merge_into
(PartialShape &dst, const PartialShape &src, const op::AutoBroadcastSpec &autob)¶ Try to merge one shape into another along with implicit broadcasting.
 Dynamic rank. (Informal notation:

class
Dimension
¶ Class representing a dimension, which may be dynamic (undetermined until runtime), in a shape or shapelike object.
Static dimensions may be implicitly converted from int64_t. A dynamic dimension is constructed with Dimension() or Dimension::dynamic().
XXX: THIS CLASS IS NOT IN USE YET AND THE ENTIRE DESIGN IS SUBJECT TO CHANGE.
Public Functions

Dimension
(int64_t dimension)¶ Construct a static dimension.
 Parameters
dimension
: Value of the dimension. Must not be equal to Dimension::s_dynamic_val.
 Exceptions
std::invalid_argument
: Ifdimension
== Dimension::s_dynamic_val.

Dimension
()¶ Construct a dynamic dimension.

bool
is_static
() const¶ Check whether this dimension is static.
 Return
true
if the dimension is static, elsefalse
.

bool
is_dynamic
() const¶ Check whether this dimension is dynamic.
 Return
false
if the dimension is static, elsetrue
.

operator int64_t
() const¶ Convert this dimension to
int64_t
. This dimension must be static. Exceptions
std::invalid_argument
: If this dimension is dynamic.

operator size_t
() const¶ Convert this dimension to
size_t
. This dimension must be static and nonnegative. Exceptions
std::invalid_argument
: If this dimension is dynamic or negative.

bool
same_scheme
(const Dimension &dim) const¶ Check whether this dimension represents the same scheme as the argument (both dynamic, or equal).
 Return
true
if this dimension anddim
are both dynamic, or if they are both static and equal; otherwise,false
. Parameters
dim
: The other dimension to compare this dimension to.

bool
compatible
(const Dimension &d) const¶ Check whether this dimension is capable of being merged with the argument dimension.
Two dimensions are considered compatible if it is possible to merge them. (See
Dimension::merge.) Return
true
if this dimension is compatible withd
, elsefalse
. Parameters
d
: The dimension to compare this dimension with.

bool
relaxes
(const Dimension &d) const¶ Check whether this dimension is a relaxation of the argument.
A dimension
d1
relaxes (or is a relaxation of)d2
ifd1
andd2
are static and equal, ord1
is dynamic. Return
true
if this dimension relaxesd
, elsefalse
. Parameters
d
: The dimension to compare this dimension with.
d1.relaxes(d2)
is equivalent tod2.refines(d1)
.

bool
refines
(const Dimension &d) const¶ Check whether this dimension is a refinement of the argument.
A dimension
d2
refines (or is a refinement of)d1
ifd1
andd2
are static and equal, ord2
is dynamic. Return
true
if this dimension relaxesd
, elsefalse
. Parameters
d
: The dimension to compare this dimension with.
d1.refines(d2)
is equivalent tod2.relaxes(d1)
.

Dimension
operator+
(const Dimension &dim) const¶ Addition operator for Dimension.
 Return
 Dimension::dynamic() if either of
*this
ordim
is dynamic; else, a static dimension with valueint64_t(*this)+in64_t(dim)
.  Parameters
dim
: Right operand for addition.

Dimension
operator
(const Dimension &dim) const¶ Subtraction operator for Dimension.
 Return
 Dimension::dynamic() if either of
*this
ordim
is dynamic; else, a static dimension with valueint64_t(*this)int64_t(dim)
.  Parameters
dim
: Right operand for subtraction.

Dimension
operator*
(const Dimension &dim) const¶ Multiplication operator for Dimension.
 Return
 0 if either of
*this
ordim
is static and 0; else, Dimension::dynamic() if either of*this
ordim
is dynamic; else, a static dimension with valueint64_t(*this)*int64_t(dim)
.  Parameters
dim
: Right operand for multiplicaiton.
Public Static Functions

bool
merge
(Dimension &dst, const Dimension d1, const Dimension d2)¶ Try to merge two Dimension objects together.
 If
d1
is dynamic, writesd2
todst
and returnstrue
.  If
d2
is dynamic, writesd1
todst
and returnstrue
.  If
d1
andd2
are static and equal, writesd1
todst
and returnstrue
.  If
d1
andd2
are both static and unequal, leavesdst
unchanged and returnsfalse
.
 Return
true
if merging succeeds, elsefalse
. Parameters
dst
: Reference to write the merged Dimension into.d1
: First dimension to merge.d2
: Second dimension to merge.
 If
Public Static Attributes

const int64_t
s_dynamic_val
= {(std::numeric_limits<int64_t>::max())}¶ Constant for the value used internally to represent a dynamic dimension.
