VK_EXT_cooperative_matrix_maintenance1.proposal
This document proposes extending support for cooperative matrices to make them more broadly useful.
Problem Statement
While VK_KHR_cooperative_matrix can be used to accelerate "simple" GEMMs, it has some serious limitations:
- Some networks require operations like reductions or matrix Use conversions, and currently these require a round trip through shared memory.
- There is no way to query for capabilities that vary by subgroup size or by class of operation (e.g. saturating accumulation).
Fortunately, VK_KHR_cooperative_matrix provides a solid foundation that we can extend to address all of these issues.
We hope that this new functionality is useful both for handwritten shaders and as a target for graph compilers.
Solution Space
This proposal includes several new features, each with their own solution spaces:
- Matrix Use conversions are important for writing fused network kernels, so that an accumulator can be used as an operand for another multiply.
- Reductions are common in networks, for example softmax activation requires a reduction over rows, and max-pooling requires a reduction over 2x2 neighborhoods. We support these in Accumulator matrices since that is the primary place they are needed. It is also possible to do sum-reduce of a row of an A matrix or a column of a B matrix by multiplying by a matrix of all ones, so we do not add an additional way to do this.
Proposal
The solution space section describes all the separate features of the proposal
and which solutions we have chosen. Then a final question is how to package these
features. Most of these can be used independently as incremental additions to
VK_KHR_cooperative_matrix. These are specified as independent feature enables
(and independent SPIR-V capabilities) so implementations can adopt them
incrementally (or they could be promoted incrementally) if needed. There are no
specific required features besides cooperativeMatrixProperties2.
Querying properties
This extension introduces a new extensible query function:
VkResult vkGetPhysicalDeviceCooperativeMatrixProperties2EXT(
VkPhysicalDevice physicalDevice,
const VkPhysicalDeviceCooperativeMatrixInfo2EXT* pCooperativeMatrixInfo,
uint32_t* pPropertyCount,
VkCooperativeMatrixProperties2EXT* pProperties);
typedef struct VkPhysicalDeviceCooperativeMatrixInfo2EXT {
VkStructureType sType;
const void* pNext;
VkScopeKHR scope;
uint32_t invocations;
uint32_t subgroupSize;
VkCooperativeMatrixFlagsEXT flags;
} VkPhysicalDeviceCooperativeMatrixInfo2EXT;
scopeis the scope of the matrix.invocationsis the number of invocations within the local workgroup.subgroupSizeis the size of the subgroup.flagsis a bitmask ofVkCooperativeMatrixFlagBitsEXTvalues selecting which class of matrix properties to query.
This subgroupSize allows the query to return matrix properties that
are specific to the provided subgroup size. A value of 0 is used to
query matrix properties that are valid for shaders executing with a
varying subgroup size (i.e. shaders created with
VK_PIPELINE_SHADER_STAGE_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT or
VK_SHADER_CREATE_ALLOW_VARYING_SUBGROUP_SIZE_BIT_EXT). For properties
returned by such a query, the implementation is permitted to choose
the effective subgroup size at runtime. Shaders that
neither force the subgroup size via
VkPipelineShaderStageRequiredSubgroupSizeCreateInfo nor enable a
varying subgroup size still have a well-defined effective subgroup size
of VkPhysicalDeviceSubgroupProperties::subgroupSize, and applications
should query with that value rather than 0 in that case.
Applications should use this new query function as the implementation may expose additional properties that are optimal or compatible only with specific subgroup sizes.
The invocations field is ignored when scope is VK_SCOPE_SUBGROUP_KHR.
When the query is used together with an extension that supports workgroup
scope cooperative matrices (such as VK_NV_cooperative_matrix2), scope
may be VK_SCOPE_WORKGROUP_KHR, in which case invocations indicates the
number of invocations in the local workgroup.
The properties are given by:
typedef struct VkCooperativeMatrixProperties2EXT {
VkStructureType sType;
void* pNext;
uint32_t MGranularity;
uint32_t NGranularity;
uint32_t KGranularity;
VkComponentTypeKHR AType;
VkComponentTypeKHR BType;
VkComponentTypeKHR CType;
VkComponentTypeKHR ResultType;
} VkCooperativeMatrixProperties2EXT;
When used together with an extension that supports flexible-dimensions
cooperative matrices (such as VK_NV_cooperative_matrix2) and the
corresponding feature is enabled, the MGranularity, NGranularity, and
KGranularity members specify the alignment of the matrix sizes,
otherwise they specify the matrix sizes equivalent to the MSize, NSize,
and KSize of
VkCooperativeMatrixPropertiesKHR.
All other members are equivalent to VkCooperativeMatrixPropertiesKHR.
Examples
A reduction computing max over each row of a matrix:
float16_t maxReduce(const in float16_t x, const in float16_t y) {
return max(x, y);
}
mat = ...;
coopmat<float16_t, gl_ScopeSubgroup, TILE_M, TILE_N, gl_MatrixUseAccumulator> rowMax;
coopMatReduceEXT (rowMax, mat, gl_CooperativeMatrixReduceRowEXT, maxReduce);
Issues
Does vkGetPhysicalDeviceCooperativeMatrixProperties2EXT supersede vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR?
RESOLVED: No, EXTs should not supersede KHR functionality. However, applications should prefer to use vkGetPhysicalDeviceCooperativeMatrixProperties2EXT in order to query more optimal matrix sizes with the provided constraints over vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR.