StableHLO는 머신의 상위 수준 작업 (HLO)을 위한 작업 집합입니다. 학습합니다. StableHLO는 여러 애플리케이션 사이의 이동성 레이어로 ML 프레임워크 및 ML 컴파일러: StableHLO 프로그램을 생성하는 ML 프레임워크 StableHLO 프로그램을 사용하는 ML 컴파일러와 호환됩니다.
Google의 목표는 더 많은 리소스를 제공하여 ML 개발을 간소화하고 가속화하는 것입니다. 다양한 ML 프레임워크 (예: TensorFlow, JAX, PyTorch) 및 ML 컴파일러 (예: XLA, IREE)를 지원합니다. 이를 위해 문서는 StableHLO 프로그래밍 언어의 사양을 제공합니다.
이 사양에는 세 개의 주요 섹션이 있습니다. 먼저 프로그램 섹션에서는 StableHLO 프로그램의 구조를 설명합니다. 이 함수는 StableHLO 함수로 구성되며 자체 StableHLO 작업으로 구성됩니다. 해당 구조 내에서 Ops 섹션은 서비스의 시맨틱스를 구성할 수 있습니다 실행 섹션은 모든 클러스터에 대한 시맨틱스를 제공합니다. 프로그램 내에서 함께 실행되는 이러한 작업을 수행합니다. 마지막으로 표기법 섹션에서는 지정할 수도 있습니다
이전 StableHLO 출시의 사양을 보려면 태그가 지정된 출시 버전에 해당합니다. 예: StableHLO v0.19.0 Spec StableHLO의 각 마이너 버전 범프에서 발생한 변경사항을 보려면 다음을 참고하세요. VhloDialect.td의 버전 로그
프로그램
Program ::= {Func}
StableHLO 프로그램은 임의의 수의 StableHLO 함수로 구성됩니다.
다음은 입력이 3개인 @main
함수가 있는 프로그램의 예입니다.
(%image
, %weights
, %bias
) 및 출력 1개. 함수의 본문
6개의 오퍼레이션이 있습니다
func.func @main(
%image: tensor<28x28xf32>,
%weights: tensor<784x10xf32>,
%bias: tensor<1x10xf32>
) -> tensor<1x10xf32> {
%0 = "stablehlo.reshape"(%image) : (tensor<28x28xf32>) -> tensor<1x784xf32>
%1 = "stablehlo.dot"(%0, %weights) : (tensor<1x784xf32>, tensor<784x10xf32>) -> tensor<1x10xf32>
%2 = "stablehlo.add"(%1, %bias) : (tensor<1x10xf32>, tensor<1x10xf32>) -> tensor<1x10xf32>
%3 = "stablehlo.constant"() {value = dense<0.0> : tensor<1x10xf32>} : () -> tensor<1x10xf32>
%4 = "stablehlo.maximum"(%2, %3) : (tensor<1x10xf32>, tensor<1x10xf32>) -> tensor<1x10xf32>
"func.return"(%4): (tensor<1x10xf32>) -> ()
}
함수
Func ::= 'func' '.' 'func' FuncId FuncInputs FuncOutputs '{' FuncBody '}'
FuncInputs ::= '(' [FuncInput {',' FuncInput}] `)`
FuncInput ::= ValueId ':' ValueType
FuncOutputs ::= ['->' FuncOutput, {',' FuncOutput}]
FuncOutput ::= ValueType
FuncBody ::= {Op}
StableHLO 함수 (이름이 지정된 함수라고도 함)에는 다음이 포함됩니다. 식별자, 입력/출력, 본문입니다. 앞으로 함수의 추가 메타데이터를 도입하여 호환성을 개선합니다. HLO (#425, #626, #740, #744)
식별자
FuncId ::= '@' letter {letter | digit}
ValueId ::= '%' digit {digit}
| '%' letter {letter | digit}
letter ::= 'a' | ... | 'z' | 'A' | ... | 'Z' | '_'
digit ::= '0' | ... | '9'
StableHLO 식별자는 많은 프로그래밍의 식별자와 유사합니다. 두 가지 특징이 있습니다. 1) 모든 식별자에는 2) 값 식별자는 StableHLO 프로그램 생성을 단순화하기 위해 완전히 숫자로 구성되어 있습니다.
유형
Type ::= ValueType | NonValueType
ValueType ::= TensorType | QuantizedTensorType | TokenType | TupleType
NonValueType ::= TensorElementType | QuantizedTensorElementType | FunctionType | StringType
안정적인 HLO 유형은 값 유형 (값 유형이라고도 함)으로 퍼스트 클래스 유형) - StableHLO 값과 비값 유형을 나타냅니다. 다른 프로그램 요소를 설명합니다. StableHLO 유형은 여러 프로그래밍 언어를 지원하며, 가장 큰 특징은 StableHLO의 비정상적인 결과를 초래하는 도메인별 특성 (예: 스칼라 유형) 는 값 유형이 아님).
TensorType ::= 'tensor' '<' Shape TensorElementType '>'
Shape ::= {DimensionSize 'x'}
DimensionSize ::= digit {digit} | '?'
텐서 유형은 텐서, 즉 다차원 배열을 나타냅니다. 그들은
셰이프 및 요소 유형: 도형은 음수가 아닌 값 또는
알 수 없는 측정기준 크기를 해당 측정기준의 오름차순으로 정렬
0
부터 R-1
까지 번호가 매겨진 측정기준 (축이라고도 함) 이
차원의 수R
를 순위라고 합니다. 예를 들어 tensor<2x3xf32>
는 다음과 같습니다.
형태가 2x3
이고 요소 유형이 f32
인 텐서 유형. 두 개의 차원이 있습니다.
(즉, 두 축) - 0번째 차원 및 첫 번째 차원 - 이 둘의 크기가
2와 3입니다. 순위는 2입니다.
셰이프는 부분적으로 또는 완전히 알 수 없을 수도 있습니다 (동적). 예: tensor<?x2xf64>
은(는) 부분적으로 알 수 없으며 tensor<?x?xf64>
은(는) 완전히 알 수 없습니다. 동적
크기 크기는 ?
를 사용하여 표시됩니다. 도형은 순위를 해제할 수 없습니다.
향후 텐서 유형을 넘어 확장 모델을 모색할 계획입니다. 치수 크기 및 요소 유형(예: 레이아웃 포함) (#629) 및 희소성 (#1078)
QuantizedTensorType ::= 'tensor' '<' Shape QuantizedTensorElementType '>'
QuantizedTensorElementType ::= '!quant.uniform' '<'
QuantizationStorageType
['<' QuantizationStorageMin ':' QuantizationStorageMax '>']
':' QuantizationExpressedType
[':' QuantizationDimension]
',' QuantizationParameters '>'
QuantizationStorageType ::= IntegerType
QuantizationStorageMin ::= IntegerConstant
QuantizationStorageMax ::= IntegerConstant
QuantizationExpressedType ::= FloatType
QuantizationDimension ::= IntegerConstant
QuantizationParameters ::= QuantizationParameter
| '{' QuantizationParameter {',' QuantizationParameter} '}'
QuantizationParameter ::= QuantizationScale ':' QuantizationZeroPoint
QuantizationScale ::= FloatConstant
QuantizationZeroPoint ::= IntegerConstant
이름 | 유형 | 제약조건 |
---|---|---|
storage_type |
정수 유형 | (C1~C3), (C8) |
storage_min |
정수 상수 | (C1), (C3), (C7) |
storage_max |
정수 상수 | (C2), (C3), (C7) |
expressed_type |
부동 소수점 유형 | (C4) |
quantization_dimension |
선택적 정수 상수 | (C10~C12) |
scales |
부동 소수점 상수의 가변 수 | (C4-C6), (C9), (C10), (C13) |
zero_points |
정수 상수의 가변 수 | (C7~C9) |
양자화된 요소 유형은 스토리지 유형의 정수 값을
다음에 해당하는 storage_min
부터 storage_max
(포함)까지의 범위
표현된 유형의 부동 소수점 값입니다. 주어진 정수 값 i
의 경우,
이에 상응하는 부동 소수점 값 f
는 다음과 같이 계산될 수 있습니다.
f = (i - zero_point) * scale
, 여기서 scale
및 zero_point
가 호출됨
양자화 매개변수입니다. storage_min
및 storage_max
는 선택사항입니다.
문법에 적용되지만 기본값은 min_value(storage_type)
및
각각 max_value(storage_type)
입니다. 양자화된 요소 유형에는
다음과 같은 제약조건이 있습니다.
- (C1)
type(storage_min) = storage_type
. - (C2)
type(storage_max) = storage_type
. - (C3)
min_value(storage_type) <= storage_min < storage_max <= max_value(storage_type)
. - (C4)
type(scales...) = expressed_type
. - (C5)
0 < scales
. - (C6)
is_finite(scales...)
. - (C7)
storage_min <= zero_points <= storage_max
. - (C8)
type(zero_points...) = storage_type
. - (C9)
size(scales) = size(zero_points)
. - (C10)
is_empty(quantization_dimension)
인 경우size(scales) = 1
. - (C11)
0 <= quantization_dimension
입니다.
현재 QuantizationScale
는 부동 소수점 상수이지만
승수와 곱셈으로 표현되는 정수 기반 척도에 대한 관심이 높음
있습니다 가까운 시일 내에 이에 대해 살펴볼 계획입니다.
(#1404)
QuantizationZeroPoint
의 의미 체계에 관한 논의가 진행 중입니다.
유형, 값, 둘 중 하나만 사용할 수 있는지
제로 포인트가 여러 개 있을 수 있습니다. 기준:
결과에 따라 0점에 관한 사양이 변경될 수 있음
(#1405)
현재 진행 중인 또 다른 논의는 QuantizationStorageMin
의 의미 체계와 관련이 있습니다.
제약 조건이 필요한지 결정하는 QuantizationStorageMax
양자화 텐서의 값과
(#1406)
마지막으로, 미지의 척도와 0을 표현하는 방법을 미지의 영역을 어떻게 파악할 계획인지와 유사하게 (#1407)
양자화 텐서 유형은 양자화 요소가 있는 텐서를 나타냅니다. 이러한 텐서는 요소가 일반 텐서와 정확히 동일하다는 점만 다릅니다. 일반 요소 유형 대신 양자화 요소 유형을 사용합니다.
양자화 텐서에서 양자화는 텐서별일 수 있습니다. 즉,
전체 텐서에 대해 하나의 scale
및 zero_point
, 또는 축당일 수 있음
즉, 여러 개의 scales
및 zero_points
이 있고 슬라이스당 한 쌍이
특정 측정기준 quantization_dimension
에 대해 자세히 알아보세요. 더 공식적으로 t
텐서에서
축당 양자화의 경우 dim(t, quantization_dimension)
개의 슬라이스가 있습니다.
quantization_dimension
: t[:, ..., 0, ..., :], t[:, ..., 1, ..., :]
,
등입니다. i
번째 슬라이스의 모든 요소는 scales[i]
및 zero_points[i]
를 다음과 같이 사용합니다.
양자화 매개변수를 생성합니다. 양자화 텐서 유형의 특징은 다음과 같습니다.
제약 조건:
- 텐서별 양자화의 경우:
<ph type="x-smartling-placeholder">
- </ph>
- 추가 제약 조건 없음
- 축당 양자화의 경우:
<ph type="x-smartling-placeholder">
- </ph>
- (C12)
quantization_dimension < rank(self)
. - (C13)
dim(self, quantization_dimension) = size(scales)
입니다.
- (C12)
TokenType ::= 'token'
토큰 유형은 토큰(즉, 생성되고 소비된 불투명 값)을 나타냅니다. 사용할 수 있습니다. 토큰은 작업의 실행 순서를 설정하는 데 사용됩니다. 실행 섹션에 설명된 대로 포함되어야 합니다.
TupleType ::= 'tuple' '<' TupleElementTypes '>'
TupleElementTypes ::= [ValueType {',' ValueType}]
튜플 유형은 튜플, 즉 이종 목록을 나타냅니다. 튜플은 유산임
HLO와의 호환성을 위해서만 존재하는 기능입니다. HLO에서 튜플은
다양한 입력과 출력을 나타내는 데 사용됩니다. StableHLO에서는 가변 입력과
출력이 기본적으로 지원되며, StableHLO에서 튜플을 유일하게 사용하는 경우는
HLO ABI를 포괄적으로 나타내야 합니다. 예를 들어 T
, tuple<T>
및
tuple<tuple<T>>
은 특정 조건에 따라 크게 다를 수 있습니다.
있습니다. 향후 HLO ABI를 변경할 계획입니다.
이를 통해 StableHLO에서 튜플 유형을 삭제할 수 있습니다.
(#598)
TensorElementType ::= BooleanType | IntegerType | FloatType | ComplexType
BooleanType ::= 'i1'
IntegerType ::= SignedIntegerType | UnsignedIntegerType
SignedIntegerType ::= 'si2' | 'si4' | 'si8' | 'si16' | 'si32' | 'si64'
UnsignedIntegerType ::= 'ui2' | 'ui4' | 'ui8' | 'ui16' | 'ui32' | 'ui64'
FloatType ::= 'f8E4M3FN' | 'f8E5M2' | 'f8E4M3FNUZ' | 'f8E5M2FNUZ'
| 'f8E4M3B11FNUZ' | 'bf16' | 'f16' | 'f32' | 'f64'
TensorFloat32 ::= 'tf32'
ComplexType ::= 'complex' '<' ComplexElementType '>'
ComplexElementType ::= 'f32' | 'f64'
요소 유형은 텐서 유형의 요소를 나타냅니다. 많은 프로그래밍에서와는 달리
이러한 유형은 StableHLO의 최고 클래스가 아닙니다. 즉,
StableHLO 프로그램은 이러한 유형의 값을 직접 나타낼 수 없으므로
0차원 텐서로 T
유형의 스칼라 값을 표현하는 것은 관용적입니다.
유형 값 tensor<T>
).
- 부울 유형은 불리언 값
true
과false
를 나타냅니다. - 정수 유형은 부호 있는 (
si
) 또는 부호 없는 (ui
)일 수 있으며 지원되는 비트 너비 (2
,4
,8
,16
,32
또는64
) 중 하나입니다. 부호 있는siN
유형은-2^(N-1)
에서2^(N-1)-1
사이의 정수 값을 나타냅니다. 부호 없는uiN
유형은0
부터2^N-1
이하입니다. - 부동 소수점 유형은 다음 중 하나일 수 있습니다.
<ph type="x-smartling-placeholder">
- </ph>
f8E4M3FN
및f8E5M2
유형이 각각 FP8 형식의E4M3
및E5M2
인코딩은 딥 러닝을 위한 FP8 형식.E4M3
및E5M2
에 해당하는f8E4M3FNUZ
및f8E5M2FNUZ
유형 FP8 형식의 인코딩은 심층신경망의 8비트 숫자 형식- FP8 형식의
E4M3
인코딩에 해당하는f8E4M3B11FNUZ
유형 설명 심층신경망을 위한 하이브리드 8비트 부동 소수점 (HFP8) 학습 및 추론. - 다음에 설명된
bfloat16
형식에 해당하는bf16
유형 BFloat16: Cloud TPU에서 고성능을 발휘하는 비결 - 각각 해당하는
f16
,f32
,f64
유형binary16
('절반 정밀도'),binary32
('단정밀도') 및binary64
('배정밀도') 형식 IEEE 754 표준을 따라야 합니다. tf32
유형은 TensorFloat32 형식에 상응 StableHLO에서 제한적으로 지원됩니다.
- 복소수 유형은 실부를 가진 복합 값을 나타냅니다.
동일한 요소 유형의 허수부를 사용합니다. 지원되는 복합
유형은
complex<f32>
(두 부분 모두f32
유형) 및complex<f64>
입니다. (두 부분 모두f64
유형입니다.)
FunctionType ::= '(' InputTypes ')' '->' '(' OutputTypes ')'
InputTypes ::= [ValueType {',' ValueType}]
OutputTypes ::= [ValueType {',' ValueType}]
함수 유형은 이름이 지정된 함수와 익명 함수를 모두 나타냅니다. 그들은
입력 유형 (->
의 왼쪽에 있는 유형 목록) 및 출력 유형
(->
오른쪽에 있는 유형 목록). 많은 프로그래밍에서
함수 유형이 최고 수준이지만 StableHLO에서는 그렇지 않습니다.
StringType ::= 'string'
문자열 유형은 바이트 시퀀스를 나타냅니다. 많은 프로그래밍에서와는 달리 문자열 유형은 StableHLO의 첫 번째 클래스가 아니며 프로그램 요소에 대한 정적 메타데이터를 지정합니다.
운영
StableHLO 작업 (작업이라고도 함)은 폐쇄형 집합을 나타냅니다. 머신러닝 모델의 개략적인 작업에 대해 알아봅니다. 위에서 설명한 것처럼 StableHLO 구문은 MLIR의 영향을 많이 받았으며, MLIR은 인체공학적 대안이지만, StableHLO의 목표인 ML 프레임워크와 ML 컴파일러 간의 상호 운용성을 높이는 데 도움이 됩니다.
Op ::= [OpOutputs] OpName OpInputs ':' OpSignature
OpName ::= '"' 'stablehlo' '.' OpMnemonic '"'
OpMnemonic ::= 'abs' | 'add' | ...
StableHLO 작업 (작업이라고도 함)의 이름은 다음과 같습니다.
입력/출력과 서명이 있습니다 이름은 stablehlo.
프리픽스와
지원되는 작업 중 하나를 고유하게 식별하는 니모닉 자세한 내용은 아래를 참고하세요.
지원되는 모든 작업의 전체 목록
OpInputs ::= OpInputValues OpInputFuncs OpInputAttrs
OpInputValues ::= '(' [OpInputValue {',' OpInputValue}] ')'
OpInputValue ::= ValueId
OpInputFuncs ::= ['(' OpInputFunc {',' OpInputFunc} ')']
OpInputAttrs ::= ['{' OpInputAttr {',' OpInputAttr} '}']
OpOutputs ::= [OpOutput {',' OpOutput} '=']
OpOutput ::= ValueId
Ops는 입력을 소비하고 출력을 생성합니다. 입력은 다음과 같이 분류됩니다.
입력 값 (실행 중에 계산됨), 입력 함수 (제공됨)
이는 StableHLO 함수가 최고 값이 아니기 때문입니다.)
입력 속성 (정적으로도 제공됨) 입력 및 출력의 종류
연산에 의해 소비되고 생성되는 작업은 니모닉에 따라 달라집니다. 예를 들면 add
입니다.
op는 2개의 입력 값을 사용하고 1개의 출력 값을 생성합니다. 이에 비해
select_and_scatter
작업은 입력 값 3개, 입력 함수 2개,
3가지 입력 속성
OpInputFunc ::= '{' Unused FuncInputs ':' FuncBody '}'
Unused ::= '^' digit {digit}
| '^' letter {letter | digit}
입력 함수 (익명 함수라고도 함)는
1) 식별자가 없고 (따라서
이름 '익명'), 2) 출력 유형을 선언하지 않는 경우 (출력 유형은
함수 내의 return
작업에서 추론됨).
입력 함수의 구문에는 현재 사용되지 않는 부분(
Unused
프로덕션)에서 사용할 수 있습니다. MLIR에서,
'지역'이라는 좀 더 일반적인 개념이 있습니다. 여기에는 여러 '블록'이
점프 오퍼레이션을 통해 연결된 오퍼레이션의 수를 뜻합니다. 이 블록에는
Unused
프로덕션에 할당하여 서로 구분할 수 있도록 합니다.
StableHLO에는 점프 오퍼레이션이 없으므로 MLIR 구문의 상응하는 부분은
여전히 존재합니다.
OpInputAttr ::= OpInputAttrName '=' OpInputAttrValue
OpInputAttrName ::= letter {letter | digit}
OpInputAttrValue ::= Constant
입력 속성에는 지원되는
상수입니다. 프로그램의 정적 메타데이터를 지정하는 기본적인 방법입니다.
요소 예를 들어 concatenate
작업은 dimension
속성을 사용하여
입력 값이 연결되는 차원을 지정합니다. 마찬가지로
slice
작업은 start_indices
및 limit_indices
와 같은 여러 속성을 사용합니다.
입력 값을 슬라이스하는 데 사용되는 경계를 지정합니다.
현재 실제 환경에서 StableHLO 프로그램에는 자세한 내용은 이 문서에서 설명하지 않습니다. 앞으로 이 속성을 StableHLO opset에 흡수하거나 StableHLO 프로그램에 표시됩니다 그 동안 속성:
layout
(#629)mhlo.frontend_attributes
(#628)mhlo.sharding
(#619)output_operand_aliases
(#740)- 위치 메타데이터 (#594)
OpSignature ::= '(' [ValueType {',' ValueType}] ')' '->' '(' [ValueType {',' ValueType}] ')'
작업 서명은 모든 입력 값의 유형 (작업에 필요한
->
) 및 모든 출력 값의 유형(
->
의 오른쪽에 있음). 엄밀히 말하면 입력 유형은
출력 유형도 거의 항상 중복됩니다.
대부분의 StableHLO 작업의 경우, 출력 유형은 입력에서 추론할 수 있음). 그럼에도 불구하고,
서명은 MLIR과의 호환성을 위해 의도적으로 StableHLO 구문의 일부입니다.
다음은 니모닉이 select_and_scatter
인 작업의 예입니다. 3개의
입력 값 (%operand
, %source
, %init_value
), 입력 함수 2개
3개의 입력 속성 (window_dimensions
, window_strides
, padding
)
작업 서명에 입력 값의 유형만 포함되는 방식에 유의하세요.
(인라인으로 제공되는 입력 함수 및 속성 유형은 제외)
%result = "stablehlo.select_and_scatter"(%operand, %source, %init_value) ({
^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):
%0 = "stablehlo.compare"(%arg0, %arg1) {
comparison_direction = #stablehlo<comparison_direction GE>
} : (tensor<i32>, tensor<i32>) -> tensor<i1>
"stablehlo.return"(%0) : (tensor<i1>) -> ()
}, {
^bb0(%arg0: tensor<i32>, %arg1: tensor<i32>):
%0 = "stablehlo.add"(%arg0, %arg1) : (tensor<i32>, tensor<i32>) -> tensor<i32>
"stablehlo.return"(%0) : (tensor<i32>) -> ()
}) {
window_dimensions = dense<[3, 1]> : tensor<2xi64>,
window_strides = dense<[2, 1]> : tensor<2xi64>,
padding = dense<[[0, 1], [0, 0]]> : tensor<2x2xi64>
} : (tensor<4x2xi32>, tensor<2x2xi32>, tensor<i32>) -> tensor<4x2xi32>
상수
Constant ::= BooleanConstant
| IntegerConstant
| FloatConstant
| ComplexConstant
| TensorConstant
| QuantizedTensorConstant
| StringConstant
| EnumConstant
StableHLO 상수에는 리터럴과 유형이 함께 있어 이 상수가
StableHLO 값입니다. 일반적으로 유형은 상수 문법의 일부입니다.
모호하지 않을 때 (예: 불리언 상수의 i1
유형이 분명하고
반면 정수 상수는 가능한 여러 유형을 가질 수 있습니다).
BooleanConstant ::= BooleanLiteral
BooleanLiteral ::= 'true' | 'false'
부울 상수는 불리언 값 true
및 false
를 나타냅니다. 불리언
상수는 i1
유형입니다.
IntegerConstant ::= IntegerLiteral ':' IntegerType
IntegerLiteral ::= ['-' | '+'] DecimalDigits
| ['-' | '+'] '0x' HexadecimalDigits
DecimalDigits ::= decimalDigit {decimalDigit}
HexadecimalDigits ::= hexadecimalDigit {hexadecimalDigit}
decimalDigit ::= '0' | ... | '9'
hexadecimalDigit ::= decimalDigit | 'a' | ... | 'f' | 'A' | ... | 'F'
정수 상수는 십진수 상수 또는 부호를 사용하는 문자열을 통해 정수 값을 나타냅니다. 16진수 표기법으로 표시됩니다. 기타 염기(예: 지원되지 않습니다. 정수 상수에는 다음과 같은 제약이 있습니다.
- (C1)
is_wellformed(integer_literal, integer_type)
.
FloatConstant ::= FloatLiteral ':' FloatType
FloatLiteral ::= SignPart IntegerPart FractionalPart ScientificPart
| '0x' [HexadecimalDigits]
SignPart ::= ['-' | '+']
IntegerPart ::= DecimalDigits
FractionalPart ::= ['.' [DecimalDigits]]
ScientificPart ::= [('e' | 'E') ['-' | '+'] DecimalDigits]
부동 소수점 상수는 십진법이나 과학적 표기법을 사용할 수 없습니다. 또한 16진법은 기본 비트를 직접 지정하는 데 사용되는 표시됩니다. 부동 소수점 상수에는 다음과 같은 제약 조건이 있습니다.
- (C1) 16진수가 아닌 표기법을 사용하는 경우
is_wellformed(float_literal, float_type)
- (C2) 16진수 표기법을 사용하는 경우
size(hexadecimal_digits) = num_bits(float_type) / 4
ComplexConstant ::= ComplexLiteral ':' ComplexType
ComplexLiteral ::= '(' RealPart ',' ImaginaryPart ')'
RealPart ::= FloatLiteral
ImaginaryPart ::= FloatLiteral
복소수 상수는 실수부의 목록을 사용하여 복합 값을 나타냅니다.
(먼저 나옴) 및 허수 부분 (두 번째가 나옴)입니다. 예를 들어
(1.0, 0.0) : complex<f32>
는 1.0 + 0.0i
를 나타냅니다.
(0.0, 1.0) : complex<f32>
는 0.0 + 1.0i
를 나타냅니다. 이러한 입력 시퀀스는
메모리에 저장됩니다. 복합 상수
다음과 같은 제약 조건이 있습니다.
- (C1)
is_wellformed(real_part, complex_element_type(complex_type))
. - (C2)
is_wellformed(imaginary_part, complex_element_type(complex_type))
.
TensorConstant ::= TensorLiteral ':' TensorType
TensorLiteral ::= 'dense' '<' (DenseLiteral | ElementLiteral) '>'
DenseLiteral ::= DenseDimension | DenseElements
DenseDimension ::= '[' [DenseLiteral {',' DenseLiteral}] ']'
DenseElements ::= [ElementLiteral {',' ElementLiteral}]
ElementLiteral ::= BooleanLiteral | IntegerLiteral | FloatLiteral | ComplexLiteral
텐서 상수는 다음을 통해 지정된 중첩 목록을 사용하여 텐서 값을 나타냅니다.
NumPy 표기법 예: dense<[[1, 2, 3], [4, 5, 6]]> : tensor<2x3xi32>
인덱스에서 요소로 다음과 같은 매핑을 사용하여 텐서 값을 나타냅니다.
{0, 0} => 1
, {0, 1} => 2
, {0, 2} => 3
, {1, 0} => 4
, {1, 1} => 5
{1, 2} => 6
이러한 요소가 메모리에 저장되는 순서는 다음과 같습니다.
구현 정의입니다. 텐서 상수에는 다음과 같은 제약 조건이 있습니다.
- (C1)
has_syntax(tensor_literal, element_type(tensor_type))
, 각 항목의 의미는 다음과 같습니다. <ph type="x-smartling-placeholder">- </ph>
has_syntax(element_literal: Syntax, element_type: Type) = is_wellformed(element_literal, type)
.has_syntax(tensor_literal: List, element_type: Type) = has_syntax(tensor_literal..., element_type)
.
- (C2)
has_shape(tensor_literal, shape(tensor_type))
, 각 항목의 의미는 다음과 같습니다. <ph type="x-smartling-placeholder">- </ph>
has_shape(element_literal: Syntax, []) = true
.has_shape(tensor_literal: List, shape: List) = size(tensor_literal) = shape[0] and has_shape(tensor_literal..., shape[1:])
.- 그렇지 않으면
false
입니다.
QuantizedTensorConstant ::= QuantizedTensorLiteral ':' QuantizedTensorType
QuantizedTensorLiteral ::= 'dense' '<' (DenseLiteral | ElementLiteral) '>'
양자화 텐서 상수는 텐서 상수인 표기법으로, 요소가 요소의 상수로 지정됨 스토리지 유형을 선택합니다 양자화 텐서 상수에는 다음과 같은 제약 조건이 있습니다.
- (C1)
has_syntax(quantized_tensor_literal, storage_type(quantized_tensor_type))
. - (C2)
has_shape(quantized_tensor_literal, shape(quantized_tensor_type))
.
StringConstant ::= StringLiteral
StringLiteral ::= '"' {stringCharacter | escapeSequence} '"'
stringCharacter ::= all ASCII characters except '\00', '\01', ... '\1f' and '"'
escapeSequence ::= '\' ('"' | '\' | 'n' | 't' | (hexadecimalDigit hexadecimalDigit))
문자열 리터럴은 ASCII 문자 및
이스케이프 문자 시퀀스입니다. 인코딩에 구애받지 않으므로 이러한 변환의 해석은
바이트는 구현이 정의됩니다. 문자열 리터럴의 유형은 string
입니다.
작업
abs
시맨틱
operand
텐서에서 요소별 abs 연산을 실행하고 result
를 생성합니다.
텐서가 포함됩니다. 요소 유형에 따라 다음 작업을 실행합니다.
- 부호 있는 정수: 정수 계수
- 부동 소수점 수: IEEE-754의
abs
- 복소수: 복소수
- 양자화 유형의 경우:
dequantize_op_quantize(abs, operand, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부호 있는 정수, 부동 소수점, 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1~C2) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부호 있는 정수 또는 부동 소수점 유형 또는 텐서당 양자화 텐서의 텐서 | (C1~C2) |
제약조건
- (C1)
shape(result) = shape(operand)
. - (C2)
baseline_element_type(result)
는 다음과 같이 정의됩니다. <ph type="x-smartling-placeholder">- </ph>
is_complex(operand)
인 경우complex_element_type(element_type(operand))
입니다.- 그 외에는
baseline_element_type(operand)
입니다.
예
// %operand: [-2, 0, 2]
%result = "stablehlo.abs"(%operand) : (tensor<3xi32>) -> tensor<3xi32>
// %result: [2, 0, 2]
추가
시맨틱
두 텐서 lhs
및 rhs
의 요소별 추가를 실행하고 다음을 생성합니다.
result
텐서. 요소 유형에 따라 다음 작업을 실행합니다.
- 불리언: 논리적 OR.
- 정수의 경우: 정수 덧셈.
- 부동 소수점 수: IEEE-754의
addition
- 복소수의 경우 복소수 더하기입니다.
- 양자화 유형의 경우:
dequantize_op_quantize(add, lhs, rhs, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | lhs |
양자화 텐서 | (C1~C6) |
(I2) | rhs |
양자화 텐서 | (C1~C5), (C7) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
양자화 텐서 | (C1~C7) |
제약조건
- 작업이 양자화되지 않은 텐서를 사용하는 경우:
<ph type="x-smartling-placeholder">
- </ph>
- (C1)
type(lhs) = type(rhs) = type(result)
.
- (C1)
- 연산이 양자화 텐서를 사용하는 경우:
<ph type="x-smartling-placeholder">
- </ph>
- (C2)
is_quantized(lhs) and is_quantized(rhs) and is_quantized(result)
. - (C3)
storage_type(lhs) = storage_type(rhs) = storage_type(result)
. - (C4)
expressed_type(lhs) = expressed_type(rhs) = expressed_type(result)
. - (C5)
(is_per_axis_quantized(lhs) or is_per_axis_quantized(rhs)) = is_per_axis_quantized(result)
. - (C6)
is_per_axis_quantized(lhs)
인 경우quantization_dimension(lhs) = quantization_dimension(result)
- (C7)
is_per_axis_quantized(rhs)
인 경우quantization_dimension(rhs) = quantization_dimension(result)
- (C2)
예
// %lhs: [[1, 2], [3, 4]]
// %rhs: [[5, 6], [7, 8]]
%result = "stablehlo.add"(%lhs, %rhs) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>
// %result: [[6, 8], [10, 12]]
after_all
시맨틱
inputs
를 생성하는 작업이
result
이 작업을 실행해도 아무 작업도 실행되지 않습니다.
result
에서 inputs
로의 데이터 종속 항목을 설정하는 용도로만 존재합니다.
입력
라벨 | 이름 | 유형 |
---|---|---|
(I1) | inputs |
token 의 가변수 |
출력
이름 | 유형 |
---|---|
result |
token |
예
// %input0: !stablehlo.token
// %input1: !stablehlo.token
%result = "stablehlo.after_all"(%input0, %input1) : (!stablehlo.token, !stablehlo.token) -> !stablehlo.token
all_gather
시맨틱
StableHLO 프로세스 그리드의 각 프로세스 그룹 내에서 값을 연결합니다.
all_gather_dim
를 따라 각 프로세스에서 operands
텐서의 반환 및
results
텐서.
이 작업은 StableHLO 프로세스 그리드를 다음과 같은 process_groups
로 분할합니다.
다음과 같이 정의됩니다.
cross_replica(replica_groups)
channel_id <= 0 and use_global_device_ids = false
인 경우.cross_replica_and_partition(replica_groups)
channel_id > 0 and use_global_device_ids = false
인 경우.flattened_ids(replica_groups)
channel_id > 0 and use_global_device_ids = true
인 경우.
그런 다음 각 process_group
내에서 다음을 실행합니다.
- 전체
operands...@receiver = [operand@sender for sender in process_group]
process_group
에서receiver
- 전체
results...@process = concatenate(operands...@process, all_gather_dim)
process_group
에서process
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operands |
텐서의 가변 수 또는 텐서당 양자화 텐서 | (C1), (C6) |
(I2) | all_gather_dim |
si64 유형의 상수 |
(C1), (C6) |
(I3) | replica_groups |
si64 유형의 2차원 텐서 상수 |
(C2~C4) |
(I4) | channel_id |
si64 유형의 상수 |
(C5) |
(I5) | use_global_device_ids |
i1 유형의 상수 |
(C5) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
results |
텐서의 가변 수 또는 텐서당 양자화 텐서 | (C6) |
제약조건
- (C1)
0 <= all_gather_dim < rank(operands...)
. - (C2)
is_unique(replica_groups)
. - (C3)
size(replica_groups)
는 다음과 같이 정의됩니다. <ph type="x-smartling-placeholder">- </ph>
cross_replica
가 사용되는 경우num_replicas
cross_replica_and_partition
가 사용되는 경우num_replicas
flattened_ids
가 사용되는 경우num_processes
- (C4)
0 <= replica_groups < size(replica_groups)
. - (C5)
use_global_device_ids = true
인 경우channel_id > 0
- (C6) 다음을 제외한
type(results...) = type(operands...)
: <ph type="x-smartling-placeholder">- </ph>
dim(results..., all_gather_dim) = dim(operands..., all_gather_dim) * dim(process_groups, 1)
.
예
// num_replicas: 2
// num_partitions: 1
// %operand0@(0, 0): [[1, 2], [3, 4]]
// %operand0@(1, 0): [[5, 6], [7, 8]]
// %operand1@(0, 0): [[11, 12], [13, 14]]
// %operand1@(1, 0): [[15, 16], [17, 18]]
%result:2 = "stablehlo.all_gather"(%operand0, %operand1) {
all_gather_dim = 1 : i64,
replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>,
// channel_id = 0
channel_handle = #stablehlo.channel_handle<handle = 0, type = 0>
// use_global_device_ids = false
} : (tensor<2x2xi64>, tensor<2x2xi64>) -> (tensor<2x4xi64>, tensor<2x4xi64>)
// %result0@(0, 0): [[1, 2, 5, 6], [3, 4, 7, 8]]
// %result0@(1, 0): [[1, 2, 5, 6], [3, 4, 7, 8]]
// %result1@(0, 0): [[11, 12, 15, 16], [13, 14, 17, 18]]
// %result1@(1, 0): [[11, 12, 15, 16], [13, 14, 17, 18]]
all_reduce
시맨틱
StableHLO 프로세스 그리드의 각 프로세스 그룹 내에서 축소를 적용합니다.
computation
함수를 각 프로세스의 operands
텐서 값에 적용
results
텐서를 생성합니다.
이 작업은 StableHLO 프로세스 그리드를 다음과 같은 process_groups
로 분할합니다.
다음과 같이 정의됩니다.
cross_replica(replica_groups)
channel_id <= 0 and use_global_device_ids = false
인 경우.cross_replica_and_partition(replica_groups)
channel_id > 0 and use_global_device_ids = false
인 경우.flattened_ids(replica_groups)
channel_id > 0 and use_global_device_ids = true
인 경우.
그런 다음 각 process_group
내에서 다음을 실행합니다.
- 일부 바이너리 트리의 경우
results...@process[result_index] = exec(schedule)
schedule
각 항목의 의미는 다음과 같습니다. <ph type="x-smartling-placeholder">- </ph>
exec(node)
=computation(exec(node.left), exec(node.right))
exec(leaf)
=leaf.value
schedule
는 순서대로 정의된 구현 정의 바이너리 트리입니다. 순회가to_destination_type(operands...@process_group...[result_index], type(func_inputs(computation)[0]))
입니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operands |
텐서의 가변 수 또는 텐서당 양자화 텐서 | (C5), (C6) |
(I2) | replica_groups |
si64 유형의 1차원 텐서 상수의 가변 수 |
(C1~C3) |
(I3) | channel_id |
si64 유형의 상수 |
(C4) |
(I4) | use_global_device_ids |
i1 유형의 상수 |
(C4) |
(I5) | computation |
함수 | (C5) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
results |
텐서의 가변 수 또는 텐서당 양자화 텐서 | (C6~C7) |
제약조건
- (C1)
is_unique(replica_groups)
. - (C2)
size(replica_groups)
는 다음과 같이 정의됩니다. <ph type="x-smartling-placeholder">- </ph>
cross_replica
가 사용되는 경우num_replicas
cross_replica_and_partition
가 사용되는 경우num_replicas
flattened_ids
가 사용되는 경우num_processes
- (C3)
0 <= replica_groups < size(replica_groups)
. - (C4)
use_global_device_ids = true
이면channel_id > 0
입니다. - (C5)
computation
에는(tensor<E>, tensor<E>) -> (tensor<E>)
유형이 있습니다. 여기서is_promotable(element_type(operand), E)
입니다. - (C6)
shape(results...) = shape(operands...)
. - (C7)
element_type(results...) = E
.
예
// num_replicas: 2
// num_partitions: 1
// %operand0@(0, 0): [1, 2, 3, 4]
// %operand0@(1, 0): [5, 6, 7, 8]
// %operand1@(0, 0): [9, 10, 11, 12]
// %operand1@(1, 0): [13, 14, 15, 16]
%result:2 = "stablehlo.all_reduce"(%operand0, %operand0) ({
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%0 = "stablehlo.add"(%arg0, %arg1) : (tensor<i64>, tensor<i64>) -> tensor<i64>
"stablehlo.return"(%0) : (tensor<i64>) -> ()
}) {
replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>,
// channel_id = 0
channel_handle = #stablehlo.channel_handle<handle = 0, type = 0>
// use_global_device_ids = false
} : (tensor<4xi64>, tensor<4xi64>) -> (tensor<4xi64>, tensor<4xi64>)
// %result0@(0, 0): [6, 8, 10, 12]
// %result0@(1, 0): [6, 8, 10, 12]
// %result1@(0, 0): [22, 24, 26, 28]
// %result1@(1, 0): [22, 24, 26, 28]
all_to_all
시맨틱
StableHLO 프로세스 그리드의 각 프로세스 그룹 내에서
split_dimension
를 따라 operands
텐서를 분할하고 분할을 분산
흩어져 있는 부품들을
concat_dimension
이고 results
텐서를 생성합니다.
이 작업은 StableHLO 프로세스 그리드를 다음과 같은 process_groups
로 분할합니다.
다음과 같이 정의됩니다.
channel_id <= 0
인 경우cross_replica(replica_groups)
입니다.channel_id > 0
인 경우cross_partition(replica_groups)
입니다.
그런 다음 각 process_group
내에서 다음을 실행합니다.
split_parts...@sender = split(operands...@sender, split_count, split_dimension)
process_group
의 모든sender
에 대해scattered_parts...@receiver = [split_parts...@sender[receiver_index] for sender in process_group]
각 항목의 의미는 다음과 같습니다.receiver_index = process_group.index(receiver)
results...@process = concatenate(scattered_parts...@process, concat_dimension)
.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operands |
텐서의 가변 수 또는 텐서당 양자화 텐서 | (C1~C3), (C9) |
(I2) | split_dimension |
si64 유형의 상수 |
(C1), (C2), (C9) |
(I3) | concat_dimension |
si64 유형의 상수 |
(C3), (C9) |
(I4) | split_count |
si64 유형의 상수 |
(C2), (C4), (C8), (C9) |
(I5) | replica_groups |
si64 유형의 2차원 텐서 상수 |
(C5~C8) |
(I6) | channel_id |
si64 유형의 상수 |
출력
이름 | 유형 | 제약조건 |
---|---|---|
results |
텐서의 가변 수 또는 텐서당 양자화 텐서 | (C9) |
제약조건
- (C1)
0 <= split_dimension < rank(operands...)
. - (C2)
dim(operands..., split_dimension) % split_count = 0
. - (C3)
0 <= concat_dimension < rank(operands...)
. - (C4)
0 < split_count
. - (C5)
is_unique(replica_groups)
. - (C6)
size(replica_groups)
는 다음과 같이 정의됩니다. <ph type="x-smartling-placeholder">- </ph>
cross_replica
가 사용되는 경우num_replicas
cross_partition
가 사용되는 경우num_partitions
- (C7)
0 <= replica_groups < size(replica_groups)
. - (C8)
dim(replica_groups, 1) = split_count
. - (C9)
type(results...) = type(operands...)
. 단,split_dimension != concat_dimension
인 경우는 예외입니다. <ph type="x-smartling-placeholder">- </ph>
dim(results..., split_dimension) = dim(operands..., split_dimension) / split_count
.dim(results..., concat_dimension) = dim(operands..., concat_dimension) * split_count
.
예
// num_replicas: 2
// num_partitions: 1
// %operand1@(0, 0): [[1, 2, 3, 4],
// [5, 6, 7, 8]]
// %operand1@(1, 0): [[9, 10, 11, 12],
// [13, 14, 15, 16]]
// %operand2@(0, 0): [[17, 18, 19, 20],
// [21, 22, 23, 24]]
// %operand2@(1, 0): [[25, 26, 27, 28],
// [29, 30, 31, 32]]
%result:2 = "stablehlo.all_to_all"(%operand1, %operand2) {
split_dimension = 1 : i64,
concat_dimension = 0 : i64,
split_count = 2 : i64,
replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>
// channel_id = 0
} : (tensor<2x4xi64>, tensor<2x4xi64>) -> (tensor<4x2xi64>, tensor<4x2xi64>)
// %result#0@(0, 0): [[1, 2], [5, 6], [9, 10], [13, 14]]
// %result#0@(1, 0): [[3, 4], [7, 8], [11, 12], [15, 16]]
// %result#1@(0, 0): [[17, 18], [21, 22], [25, 26], [29, 30]]
// %result#1@(1, 0): [[19, 20], [23, 24], [27, 28], [31, 32]]
및
시맨틱
두 텐서 lhs
및 rhs
의 요소별 AND를 실행하고 result
를 생성합니다.
텐서가 포함됩니다. 요소 유형에 따라 다음 작업을 실행합니다.
- 불리언: 논리적 AND.
- 정수: 비트 AND
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | lhs |
부울 또는 정수 유형의 텐서 | (C1) |
(I2) | rhs |
부울 또는 정수 유형의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부울 또는 정수 유형의 텐서 | (C1) |
제약조건
- (C1)
type(lhs) = type(rhs) = type(result)
.
예
// %lhs: [[1, 2], [3, 4]]
// %rhs: [[5, 6], [7, 8]]
%result = "stablehlo.and"(%lhs, %rhs) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>
// %result: [[1, 2], [3, 0]]
atan2
시맨틱
lhs
및 rhs
텐서에서 요소별 atan2 연산을 실행하고 다음을 생성합니다.
result
텐서. 요소 유형에 따라 다음 작업을 실행합니다.
- 부동 소수점 수: IEEE-754의
atan2
- 복소수의 경우 복소수 atan2입니다.
- 양자화 유형의 경우:
dequantize_op_quantize(atan2, lhs, rhs, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | lhs |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
(I2) | rhs |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(lhs) = baseline_type(rhs) = baseline_type(result)
.
예
// %lhs: [0.0, 1.0, -1.0]
// %rhs: [0.0, 0.0, 0.0]
%result = "stablehlo.atan2"(%lhs, %rhs) : (tensor<3xf64>, tensor<3xf64>) -> tensor<3xf64>
// %result: [0.0, 1.57079637, -1.57079637] // [0.0, pi/2, -pi/2]
batch_norm_grad
시맨틱
batch_norm_training
역전파의 여러 입력의 경사를 계산합니다.
grad_output
에서 grad_operand
, grad_scale
, grad_offset
를 생성
텐서 등이 포함됩니다 더 공식적으로 이 작업은
기존의 StableHLO 작업을 실행할 수 있습니다.
def compute_sum(operand, feature_index):
(sum,) = reduce(
inputs=[operand],
init_values=[constant(0, element_type(operand))],
dimensions=[i for i in range(rank(operand)) if i != feature_index],
body=lambda x, y: add(x, y))
return sum
def compute_mean(operand, feature_index):
sum = compute_sum(operand, feature_index)
divisor = constant(size(operand) / dim(operand, feature_index),
element_type(operand))
divisor_bcast = broadcast_in_dim(divisor, [], type(sum))
return divide(sum, divisor_bcast)
def batch_norm_grad(operand, scale, mean, variance, grad_output, epsilon, feature_index):
# Broadcast inputs to type(operand)
scale_bcast = broadcast_in_dim(scale, [feature_index], type(operand))
mean_bcast = broadcast_in_dim(mean, [feature_index], type(operand))
variance_bcast = broadcast_in_dim(variance, [feature_index], type(operand))
epsilon_bcast = broadcast_in_dim(constant(epsilon, element_type(operand)), [],
type(operand))
# Perform normalization using the provided `mean` and `variance`
# Intermediate values will be useful for computing gradients
centered_operand = subtract(operand, mean_bcast)
stddev = sqrt(add(variance_bcast, epsilon_bcast))
normalized_operand = divide(centered_operand, stddev)
# Use the implementation from batchnorm_expander.cc in XLA
# Temporary variables have exactly the same names as in the C++ code
elements_per_feature = broadcast_in_dim(
constant(divide(size(operand), dim(operand, feature_index)),
element_type(grad_output)),
[], type(operand))
i1 = multiply(grad_output, elements_per_feature)
i2 = broadcast_in_dim(
compute_sum(grad_output, feature_index), [feature_index], type(operand))
i3 = broadcast_in_dim(
compute_sum(multiply(grad_output, centered_operand), feature_index),
[feature_index], type(operand))
i4 = multiply(i3, centered_operand)
i5 = divide(i4, add(variance_bcast, epsilon_bcast))
i6 = subtract(subtract(i1, i2), i5)
grad_operand =
multiply(divide(divide(scale_bcast, stddev), elements_per_feature), i6)
grad_scale =
compute_sum(multiply(grad_output, normalized_operand), feature_index)
grad_offset = compute_sum(grad_output, feature_index)
return grad_operand, grad_scale, grad_offset
양자화 유형의 경우
dequantize_batch_norm_grad_or_training_quantize(lambda operand, scale, mean,
variance, grad_output: batch_norm_grad(operand, scale, mean, variance,
grad_output, epsilon, feature_index), operand, scale, mean, variance,
grad_output, type(grad_operand), type(grad_scale), type(feature_index))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 유형 또는 텐서당 양자화 텐서의 텐서 | (C1~C3), (C5) |
(I2) | scale |
부동 소수점 또는 텐서당 양자화 유형의 1차원 텐서 | (C2), (C4), (C5) |
(I3) | mean |
부동 소수점 또는 텐서당 양자화 유형의 1차원 텐서 | (C2), (C4) |
(I4) | variance |
부동 소수점 또는 텐서당 양자화 유형의 1차원 텐서 | (C2), (C4) |
(I5) | grad_output |
부동 소수점 유형 또는 텐서당 양자화 텐서의 텐서 | (C2), (C3) |
(I6) | epsilon |
f32 유형의 상수 |
|
(I7) | feature_index |
si64 유형의 상수 |
(C1), (C5) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
grad_operand |
부동 소수점 유형 또는 텐서당 양자화 텐서의 텐서 | (C2), (C3) |
grad_scale |
부동 소수점 또는 텐서당 양자화 유형의 1차원 텐서 | (C2), (C4) |
grad_offset |
부동 소수점 또는 텐서당 양자화 유형의 1차원 텐서 | (C2), (C4) |
제약조건
- (C1)
0 <= feature_index < rank(operand)
. - (C2)
operand
,scale
,mean
,variance
,grad_output
,grad_operand
grad_scale
및grad_offset
의baseline_element_type
가 동일합니다. - (C3)
operand
,grad_output
,grad_operand
의 형태가 동일합니다. - (C4)
scale
,mean
,variance
,grad_scale
,grad_offset
는 같은 형태입니다. - (C5)
size(scale) = dim(operand, feature_index)
.
예
// %operand: [
// [[1.0, 2.0], [3.0, 4.0]],
// [[3.0, 4.0], [1.0, 2.0]]
// ]
// %scale: [1.0, 1.0]
// %mean: [2.0, 3.0]
// %variance: [1.0, 1.0]
// %grad_output: [
// [[0.1, 0.1], [0.1, 0.1]],
// [[0.1, 0.1], [0.1, 0.1]]
// ]
%grad_operand, %grad_scale, %grad_offset =
"stablehlo.batch_norm_grad"(%operand, %scale, %mean, %variance, %grad_output) {
epsilon = 0.0 : f32,
feature_index = 2 : i64
} : (tensor<2x2x2xf64>, tensor<2xf64>, tensor<2xf64>, tensor<2xf64>,
tensor<2x2x2xf64>) -> (tensor<2x2x2xf64>, tensor<2xf64>, tensor<2xf64>)
// %grad_operand: [
// [[0.0, 0.0], [0.0, 0.0]],
// [[0.0, 0.0], [0.0, 0.0]]
// ]
// %grad_scale: [0.0, 0.0]
// %grad_offset: [0.4, 0.4]
batch_norm_inference
시맨틱
다음을 제외한 모든 차원에서 operand
텐서를 정규화합니다.
feature_index
차원이며 result
텐서를 생성합니다. 더 공식적으로
기존 StableHLO 작업에 대한 분해로 표현할 수 있습니다.
사용하여 다음 명령어를 실행합니다.
def batch_norm_inference(operand, scale, offset, mean, variance, epsilon, feature_index):
# Broadcast inputs to shape(operand)
scale_bcast = broadcast_in_dim(scale, [feature_index], type(operand))
offset_bcast = broadcast_in_dim(offset, [feature_index], type(operand))
mean_bcast = broadcast_in_dim(mean, [feature_index], type(operand))
variance_bcast = broadcast_in_dim(variance, [feature_index], type(operand))
epsilon_bcast = broadcast_in_dim(constant(epsilon, element_type(operand)), [],
type(operand))
# Perform normalization using the provided `mean` and `variance` instead of
# computing them like `batch_norm_training` does.
centered_operand = subtract(operand, mean_bcast)
stddev = sqrt(add(variance_bcast, epsilon_bcast))
normalized_operand = divide(centered_operand, stddev)
return add(multiply(scale_bcast, normalized_operand), offset_bcast)
양자화 유형의 경우
dequantize_op_quantize(lambda operand, scale, offset, mean, variance:
batch_norm_inference(operand, scale, offset, mean, variance, epsilon,
feature_index), operand, scale, offset, mean, variance, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 유형 또는 텐서당 양자화 텐서의 텐서 | (C1~C7) |
(I2) | scale |
부동 소수점 또는 텐서당 양자화 유형의 1차원 텐서 | (C2), (C3) |
(I3) | offset |
부동 소수점 또는 텐서당 양자화 유형의 1차원 텐서 | (C2), (C4) |
(I4) | mean |
부동 소수점 또는 텐서당 양자화 유형의 1차원 텐서 | (C5) |
(I5) | variance |
부동 소수점 또는 텐서당 양자화 유형의 1차원 텐서 | (C2), (C6) |
(I6) | epsilon |
f32 유형의 상수 |
|
(I7) | feature_index |
si64 유형의 상수 |
(C1), (C3~C6) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 유형 또는 텐서당 양자화 텐서의 텐서 | (C2), (C7) |
제약조건
- (C1)
0 <= feature_index < rank(operand)
. - (C2)
operand
,scale
,offset
,mean
,variance
,result
는 동일한baseline_element_type
- (C3)
size(scale) = dim(operand, feature_index)
. - (C4)
size(offset) = dim(operand, feature_index)
. - (C5)
size(mean) = dim(operand, feature_index)
. - (C6)
size(variance) = dim(operand, feature_index)
. - (C7)
baseline_type(operand) = baseline_type(result)
.
예
// %operand: [
// [[1.0, 2.0], [3.0, 4.0]],
// [[3.0, 4.0], [1.0, 2.0]]
// ]
// %scale: [1.0, 1.0]
// %offset: [1.0, 1.0]
// %mean: [2.0, 3.0]
// %variance: [1.0, 1.0]
%result = "stablehlo.batch_norm_inference"(%operand, %scale, %offset, %mean, %variance) {
epsilon = 0.0 : f32,
feature_index = 2 : i64
} : (tensor<2x2x2xf64>, tensor<2xf64>, tensor<2xf64>, tensor<2xf64>, tensor<2xf64>) -> tensor<2x2x2xf64>
// %result: [
// [[0.0, 0.0], [2.0, 2.0]],
// [[2.0, 2.0], [0.0, 0.0]]
// ]
batch_norm_training
시맨틱
feature_index
를 제외한 모든 측정기준에서 평균과 분산을 계산합니다.
차원을 수행하고 output
, batch_mean
를 생성하는 operand
텐서를 정규화합니다.
batch_var
텐서가 포함됩니다. 더 공식적으로 이 연산은
기존 StableHLO 작업으로 분해할 수 있는데,
다음과 같습니다.
def compute_mean(operand, feature_index):
(sum,) = reduce(
inputs=[operand],
init_values=[constant(0, element_type(operand))],
dimensions=[i for i in range(rank(operand)) if i != feature_index],
body=lambda x, y: add(x, y))
divisor = constant(size(operand) / dim(operand, feature_index),
element_type(operand))
divisor_bcast = broadcast_in_dim(divisor, [], type(sum))
return divide(sum, divisor_bcast)
def compute_variance(operand, feature_index):
mean = compute_mean(operand, feature_index)
mean_bcast = broadcast_in_dim(mean, [feature_index], type(operand))
centered_operand = subtract(operand, mean_bcast)
return compute_mean(mul(centered_operand, centered_operand), feature_index)
def batch_norm_training(operand, scale, offset, epsilon, feature_index):
mean = compute_mean(operand, feature_index)
variance = compute_variance(operand, feature_index)
return batch_norm_inference(operand, scale, offset, mean, variance, epsilon,
feature_index),
mean, variance
양자화 유형의 경우
dequantize_batch_norm_grad_or_training_quantize(lambda operand, scale, offset:
batch_norm_training(operand, scale, offset, epsilon, feature_index), operand,
scale, offset, type(output), type(batch_mean), type(batch_var))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
(I2) | scale |
부동 소수점 또는 텐서당 양자화된 1차원 텐서 | (C2), (C3) |
(I3) | offset |
부동 소수점 또는 텐서당 양자화된 1차원 텐서 | (C2), (C4) |
(I4) | epsilon |
f32 유형의 상수 |
(C1), (C3~C6) |
(I5) | feature_index |
si64 유형의 상수 |
(C1), (C3~C6) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
output |
부동 소수점 유형 또는 텐서당 양자화 텐서의 텐서 | (C7) |
batch_mean |
부동 소수점 또는 텐서당 양자화된 1차원 텐서 | (C2), (C5) |
batch_var |
부동 소수점 또는 텐서당 양자화된 1차원 텐서 | (C2), (C6) |
제약조건
- (C1)
0 <= feature_index < rank(operand)
. - (C2)
operand
,scale
,offset
,batch_mean
,batch_var
및output
는 동일한baseline_element_type
입니다. - (C3)
size(scale) = dim(operand, feature_index)
. - (C4)
size(offset) = dim(operand, feature_index)
. - (C5)
size(batch_mean) = dim(operand, feature_index)
. - (C6)
size(batch_var) = dim(operand, feature_index)
. - (C7)
baseline_type(output) = baseline_type(operand)
.
예
// %operand: [
// [[1.0, 2.0], [3.0, 4.0]],
// [[3.0, 4.0], [1.0, 2.0]]
// ]
// %scale: [1.0, 1.0]
// %offset: [1.0, 1.0]
%output, %batch_mean, %batch_var = "stablehlo.batch_norm_training"(%operand, %scale, %offset) {
epsilon = 0.0 : f32,
feature_index = 2 : i64
} : (tensor<2x2x2xf64>, tensor<2xf64>, tensor<2xf64>) ->
(tensor<2x2x2xf64>, tensor<2xf64>, tensor<2xf64>)
// %output: [
// [[0.0, 0.0], [2.0, 2.0]],
// [[2.0, 2.0], [0.0, 0.0]]
// ]
// %batch_mean: [2.0, 3.0]
// %batch_var: [1.0, 1.0]
bitcast_convert
시맨틱
operand
텐서에서 비트캐스트 작업을 실행하고 result
텐서를 생성합니다.
여기서 전체 operand
텐서의 비트는
result
텐서의 유형입니다.
좀 더 공식적으로 E = element_type(operand)
, E' = element_type(result)
가 주어진 경우,
및 R = rank(operand)
:
num_bits(E') < num_bits(E)
인 경우,bits(result[i0, ..., iR-1, :]) = bits(operand[i0, ..., iR-1])
num_bits(E') > num_bits(E)
인 경우,bits(result[i0, ..., iR-2]) = bits(operand[i0, ..., iR-2, :])
num_bits(E') = num_bits(E)
인 경우,bits(result[i0, ..., iR-1]) = bits(operand[i0, ..., iR-1])
bits
는 지정된 값의 메모리 내 표현과 그 동작을 반환합니다.
텐서의 정확한 표현이
구현 정의되고 요소 유형의 정확한 표현은
정의할 수도 있습니다
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
양자화 텐서 | (C1~C2) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
양자화 텐서 | (C1~C2) |
제약조건
- (C1) 주어진
E = is_quantized(operand) ? storage_type(operand) : element_type(operand)
,E' = is_quantized(result) ? storage_type(result) : element_type(result)
,R = rank(operand)
는 다음과 같습니다. <ph type="x-smartling-placeholder">- </ph>
num_bits(E') = num_bits(E)
인 경우shape(result) = shape(operand)
입니다.num_bits(E') < num_bits(E)
인 경우:rank(result) = R + 1
.- 모든
0 <= i < R
의dim(result, i) = dim(operand, i)
dim(result, R) * num_bits(E') = num_bits(E)
.num_bits(E') > num_bits(E)
인 경우:rank(result) = R - 1
.- 모든
0 <= i < R
의dim(result, i) = dim(operand, i)
dim(operand, R - 1) * num_bits(E) = num_bits(E')
.
- (C2)
is_complex(operand) or is_complex(result)
인 경우is_complex(operand) and is_complex(result)
예
// %operand: 0x0123456789ABCDEF
%result = "stablehlo.bitcast_convert"(%operand) : (tensor<f64>) -> tensor<4xf16>
// %result: [0xCDEF, 0x89AB, 0x4567, 0x0123] // little-endian representation
broadcast_in_dim
시맨틱
데이터를 복제하여 입력 텐서의 차원 또는 순위를 확장합니다.
operand
텐서에서 생성하고 result
텐서를 생성합니다. 더 공식적으로
result[result_index] = operand[operand_index]
, 여기서 모든 d
axes(operand)
:
dim(operand, d) = 1
인 경우operand_index[d] = 0
입니다.- 그 외에는
operand_index[d] = result_index[broadcast_dimensions[d]]
입니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
양자화 텐서 | (C1~C2), (C5~C6) |
(I2) | broadcast_dimensions |
si64 유형의 1차원 텐서 상수 |
(C2~C6) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
양자화 텐서 | (C1), (C3), (C5-C6) |
제약조건
- (C1)
element_type(result)
는 다음과 같이 주어집니다. <ph type="x-smartling-placeholder">- </ph>
!is_per_axis_quantized(operand)
인 경우element_type(operand)
입니다.- 다음
quantization_dimension(operand)
를 제외하고element_type(operand)
scales(operand)
,zero_points(operand)
은quantization_dimension(result)
,scales(result)
,zero_points(result)
resp.만 사용합니다.
- (C2)
size(broadcast_dimensions) = rank(operand)
. - (C3)
0 <= broadcast_dimensions < rank(result)
. - (C4)
is_unique(broadcast_dimensions)
. - (C5)
axes(operand)
의 모든d
의 경우: <ph type="x-smartling-placeholder">- </ph>
dim(operand, d) = 1
또는dim(operand, d) = dim(result, broadcast_dimensions[d])
.
- (C6)
is_per_axis_quantized(result)
인 경우: <ph type="x-smartling-placeholder">- </ph>
quantization_dimension(result) = broadcast_dimensions[quantization_dimension(operand)]
.dim(operand, quantization_dimension(operand)) = 1
인 경우scales(result)[i] = scales(operand)[0] and zero_points(result)[i] = zero_points(operand)[0] for i in range(dim(result, quantization_dimension(result)))
예
// %operand: [
// [1, 2, 3]
// ]
%result = "stablehlo.broadcast_in_dim"(%operand) {
broadcast_dimensions = array<i64: 2, 1>
} : (tensor<1x3xi32>) -> tensor<2x3x2xi32>
// %result: [
// [
// [1, 1],
// [2, 2],
// [3, 3]
// ],
// [
// [1, 1],
// [2, 2],
// [3, 3]
// ]
// ]
케이스
시맨틱
branches
에서 정확히 함수 1개를 실행하여 출력을 생성합니다.
index
의 값에 따라 달라집니다. 더 격식 있는 표현으로 result = selected_branch()
각 항목의 의미는 다음과 같습니다.
0 <= index < size(branches)
인 경우selected_branch = branches[index]
입니다.- 그 외에는
selected_branch = branches[-1]
입니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | index |
si32 유형의 0차원 텐서 |
|
(I2) | branches |
다양한 함수 | (C1~C4) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
results |
텐서, 양자화 텐서 또는 토큰의 가변 수 | (C4) |
제약조건
- (C1)
0 < size(branches)
. - (C2)
input_types(branches...) = []
. - (C3)
same(output_types(branches...))
. - (C4)
type(results...) = output_types(branches[0])
.
예
// %index: -1
// %result_branch0: [0, 0]
// %result_branch1: [1, 1]
%result0, %result1 = "stablehlo.case"(%index) ({
"stablehlo.return"(%result_branch0, %result_branch0) : (tensor<2xi64>, tensor<2xi64>) -> ()
}, {
"stablehlo.return"(%result_branch1, %result_branch1) : (tensor<2xi64>, tensor<2xi64>) -> ()
}) : (tensor<i32>) -> (tensor<2xi64>, tensor<2xi64>)
// %result0: [1, 1]
// %result1: [1, 1]
cbrt
시맨틱
operand
텐서에서 요소별 세제곱근 연산을 실행하고 다음을 생성합니다.
result
텐서. 요소 유형에 따라 다음 작업을 실행합니다.
- 부동 소수점 수: IEEE-754의
rootn(x, 3)
- 복소수의 경우: 복소수 세제곱근을 사용합니다.
- 양자화 유형의 경우:
dequantize_op_quantize(cbrt, operand, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// %operand: [0.0, 1.0, 8.0, 27.0]
%result = "stablehlo.cbrt"(%operand) : (tensor<4xf64>) -> tensor<4xf64>
// %result: [0.0, 1.0, 2.0, 3.0]
ceil
시맨틱
operand
텐서의 요소별 ceil을 실행하고 result
텐서를 생성합니다.
IEEE-754에서 roundToIntegralTowardPositive
작업을 구현합니다.
지정할 수도 있습니다 양자화 유형의 경우
dequantize_op_quantize(ceil, operand, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// %operand: [-0.8166, -0.2530, 0.2530, 0.8166, 2.0]
%result = "stablehlo.ceil"(%operand) : (tensor<5xf32>) -> tensor<5xf32>
// %result: [-0.0, -0.0, 1.0, 1.0, 2.0]
콜레스키
시맨틱
행렬 배치의 콜레스키 분해를 계산합니다.
더 공식적으로 index_space(result)
의 모든 i
에 대해
result[i0, ..., iR-3, :, :]
는 다음의 콜레스키 분해입니다.
a[i0, ..., iR-3, :, :]
(하삼각형 중 하나)
(lower
가 true
인 경우) 또는 위쪽 삼각형 (lower
이 false
인 경우) 행렬입니다.
반대 삼각형의 출력 값(즉, 엄격한 위쪽 삼각형 또는
해당하는 엄격한 하단 삼각형은 구현으로 정의됩니다.
입력 행렬이 허미트 양함수가 아닌 i
이 존재하는 경우
행렬이면 동작이 정의되지 않습니다.
양자화 유형의 경우
dequantize_op_quantize(lambda operand: cholesky(operand, lower), a, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | a |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1~C3) |
(I2) | lower |
i1 유형의 0차원 텐서 상수 |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(a) = baseline_type(result)
. - (C2)
2 <= rank(a)
. - (C3)
dim(a, -2) = dim(a, -1)
.
예
// %a: [
// [1.0, 2.0, 3.0],
// [2.0, 20.0, 26.0],
// [3.0, 26.0, 70.0]
// ]
%result = "stablehlo.cholesky"(%a) {
lower = true
} : (tensor<3x3xf32>) -> tensor<3x3xf64>
// %result: [
// [1.0, 0.0, 0.0],
// [2.0, 4.0, 0.0],
// [3.0, 5.0, 6.0]
// ]
고정하다
시맨틱
operand
텐서의 모든 요소를 최솟값과 최댓값 사이에 고정합니다.
값을 생성하고 result
텐서를 생성합니다. 더 공식적으로 result[result_index] =
minimum(maximum(operand[result_index], min_element), max_element)
,
여기서 min_element = rank(min) = 0 ? min[] : min[result_index]
,
max_element = rank(max) = 0 ? max[] : max[result_index]
입니다. 양자화 유형의 경우
dequantize_op_quantize(clamp, min, operand, max, type(result))
를 실행합니다.
복소수에 대한 순서 지정에는 놀라운 의미 체계가 수반됩니다. 앞으로 복소수에 대한 지원을 중단할 계획입니다. (#560)
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | min |
텐서 또는 텐서당 양자화 텐서 | (C1), (C3) |
(I2) | operand |
텐서 또는 텐서당 양자화 텐서 | (C1~C4) |
(I3) | max |
텐서 또는 텐서당 양자화 텐서 | (C2), (C3) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서 또는 텐서당 양자화 텐서 | (C4) |
제약조건
- (C1)
rank(min) = 0 or shape(min) = shape(operand)
. - (C2)
rank(max) = 0 or shape(max) = shape(operand)
. - (C3)
baseline_element_type(min) = baseline_element_type(operand) = baseline_element_type(max)
. - (C4)
baseline_type(operand) = baseline_type(result)
.
예
// %min: [5, 10, 15]
// %operand: [3, 13, 23]
// %max: [10, 15, 20]
%result = "stablehlo.clamp"(%min, %operand, %max) : (tensor<3xi32>, tensor<3xi32>, tensor<3xi32>) -> tensor<3xi32>
// %result: [5, 13, 20]
collective_broadcast
시맨틱
StableHLO 프로세스 그리드의 각 프로세스 그룹 내에서
operand
텐서를 설정하여 대상 프로세스로 이동하고
result
텐서.
이 작업은 StableHLO 프로세스 그리드를 다음과 같은 process_groups
로 분할합니다.
다음과 같이 정의됩니다.
channel_id <= 0
인 경우cross_replica(replica_groups)
입니다.channel_id > 0
인 경우cross_partition(replica_groups)
입니다.
이후 result@process
는 다음과 같이 지정됩니다.
- 프로세스가 다음과 같은
i
이 있는 경우operand@process_groups[i, 0]
(process_groups[i]
) broadcast_in_dim(constant(is_quantized(result) ? quantize(0, element_type(result)) : 0, element_type(result)), [], type(result))
없습니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
텐서 또는 텐서당 양자화 텐서 | (C3) |
(I2) | replica_groups |
si64 유형의 1차원 텐서 상수의 가변 수 |
(C1), (C2) |
(I3) | channel_id |
si64 유형의 상수 |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서 또는 텐서당 양자화 텐서 | (C3) |
제약조건
- (C1)
is_unique(replica_groups)
. - (C2)
0 <= replica_groups < N
, 여기서N
는 다음과 같이 정의됩니다. <ph type="x-smartling-placeholder">- </ph>
cross_replica
가 사용되는 경우num_replicas
cross_partition
가 사용되는 경우num_partitions
- (C3)
type(result) = type(operand)
.
예
// num_replicas: 4
// num_partitions: 1
// %operand@(0, 0): [[1, 2]]
// %operand@(1, 0): [[3, 4]]
// %operand@(2, 0): [[5, 6]]
// %operand@(3, 0): [[7, 8]]
%result = "stablehlo.collective_broadcast"(%operand) {
replica_groups = dense<[[2, 1]]> : tensor<1x2xi64>,
channel_handle = #stablehlo.channel_handle<handle = 0, type = 0>
} : (tensor1x2xi64>) -> tensor<1x2xi64>
// %result@(0, 0): [[0, 0]]
// %result@(1, 0): [[5, 6]]
// %result@(2, 0): [[5, 6]]
// %result@(3, 0): [[0, 0]]
collective_permute
시맨틱
StableHLO 프로세스 그리드의 각 프로세스 그룹 내에서
operand
텐서를 출력하며
result
텐서.
이 작업은 StableHLO 프로세스 그리드를 다음과 같은 process_groups
로 분할합니다.
다음과 같이 정의됩니다.
channel_id <= 0
인 경우cross_replica(source_target_pairs)
입니다.channel_id > 0
인 경우cross_partition(source_target_pairs)
입니다.
이후 result@process
는 다음과 같이 지정됩니다.
operand@process_groups[i, 0]
: 다음과 같은i
가 존재하는 경우process_groups[i, 1] = process
입니다.broadcast_in_dim(constant(is_quantized(result) ? quantize(0, element_type(result)) : 0, element_type(result)), [], type(result))
없습니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
텐서 또는 텐서당 양자화 텐서 | (C5) |
(I2) | source_target_pairs |
si64 유형의 2차원 텐서 상수 |
(C1~C4) |
(I3) | channel_id |
si64 유형의 상수 |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서 또는 텐서당 양자화 텐서 | (C1) |
제약조건
- (C1)
dim(source_target_pairs, 1) = 2
. - (C2)
is_unique(source_target_pairs[:, 0])
. - (C3)
is_unique(source_target_pairs[:, 1])
. - (C4)
0 <= source_target_pairs < N
, 여기서N
는 다음과 같이 정의됩니다. <ph type="x-smartling-placeholder">- </ph>
cross_replica
가 사용되는 경우num_replicas
cross_partition
가 사용되는 경우num_partitions
- (C5)
type(result) = type(operand)
.
예
// num_replicas: 3
// num_partitions: 1
// %operand@(0, 0): [[1, 2], [3, 4]]
// %operand@(1, 0): [[5, 6], [7, 8]]
// %operand@(2, 0): [[9, 10], [11, 12]]
%result = "stablehlo.collective_permute"(%operand) {
source_target_pairs = dense<[[0, 1], [1, 2]]> : tensor<2x2xi64>,
channel_handle = #stablehlo.channel_handle<handle = 0, type = 0>
} : (tensor<2x2xi64>) -> tensor<2x2xi64>
//
// %result@(0, 0): [[0, 0], [0, 0]]
// %result@(1, 0): [[1, 2], [3, 4]]
// %result@(2, 0): [[5, 6], [7, 8]]
compare
시맨틱
다음에 따라 lhs
및 rhs
텐서의 요소별 비교를 실행합니다.
comparison_direction
및 compare_type
를 생성하고 result
텐서를 생성합니다.
comparison_direction
및 compare_type
의 값은 다음과 같습니다.
의미론:
부울 및 정수 요소 유형의 경우:
EQ
:lhs = rhs
.NE
:lhs != rhs
.GE
:lhs >= rhs
.GT
:lhs > rhs
.LE
:lhs <= rhs
.LT
:lhs < rhs
.
compare_type = FLOAT
가 있는 부동 소수점 요소 유형의 경우 작업은 다음을 구현합니다.
다음 IEEE-754 연산을 지원합니다.
EQ
:compareQuietEqual
.NE
:compareQuietNotEqual
.GE
:compareQuietGreaterEqual
.GT
:compareQuietGreater
.LE
:compareQuietLessEqual
.LT
:compareQuietLess
.
compare_type = TOTALORDER
가 있는 부동 소수점 요소 유형의 경우 연산
는totalOrder
compareQuietEqual
IEEE 754
복잡한 요소 유형의 경우 (real, imag)
쌍의 사전식 비교는 다음과 같습니다.
제공된 comparison_direction
및 compare_type
를 사용하여 수행됩니다.
복소수에 대한 순서 지정에는 놀라운 의미 체계가 수반됩니다.
앞으로 복소수에 대한 지원을 중단할 계획입니다.
comparison_direction
이 GE
, GT
, LE
, LT
인 경우
(#560)
양자화 유형의 경우 dequantize_compare(lhs, rhs,
comparison_direction)
를 실행합니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | lhs |
텐서 또는 텐서당 양자화 텐서 | (C1~C3) |
(I2) | rhs |
텐서 또는 텐서당 양자화 텐서 | (C1~C2) |
(I3) | comparison_direction |
EQ , NE , GE , GT , LE , LT 의 열거형 |
|
(I4) | compare_type |
FLOAT , TOTALORDER , SIGNED , UNSIGNED 의 열거형 |
(C3) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
불리언 유형의 텐서 | (C2) |
제약조건
- (C1)
baseline_element_type(lhs) = baseline_element_type(rhs)
. - (C2)
shape(lhs) = shape(rhs) = shape(result)
. - (C3)
compare_type
는 다음과 같이 정의됩니다. <ph type="x-smartling-placeholder">- </ph>
is_signed_integer(element_type(lhs))
인 경우SIGNED
입니다.is_unsigned_integer(element_type(lhs)) or is_boolean(element_type(lhs))
인 경우UNSIGNED
입니다.FLOAT
또는TOTALORDER
(is_float(element_type(lhs))
인 경우)is_complex(element_type(lhs))
인 경우FLOAT
입니다.
예
// %lhs: [1.0, 3.0]
// %rhs: [1.1, 2.9]
%result = "stablehlo.compare"(%lhs, %rhs) {
comparison_direction = #stablehlo<comparison_direction LT>,
compare_type = #stablehlo<comparison_type FLOAT>
} : (tensor<2xf32>, tensor<2xf32>) -> tensor<2xi1>
// %result: [true, false]
복잡함
시맨틱
한 쌍의 실수 및
허수 값 lhs
과 rhs
을 생성하고 result
텐서를 생성합니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | lhs |
f32 또는 f64 유형의 텐서 |
(C1~C3) |
(I2) | rhs |
f32 또는 f64 유형의 텐서 |
(C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
복합 유형의 텐서 | (C2), (C3) |
제약조건
- (C1)
type(lhs) = type(rhs)
. - (C2)
shape(result) = shape(lhs)
. - (C3)
element_type(result)
에는complex<E>
유형이 있습니다. 여기서E = element_type(lhs)
입니다.
예
// %lhs: [1.0, 3.0]
// %rhs: [2.0, 4.0]
%result = "stablehlo.complex"(%lhs, %rhs) : (tensor<2xf64>, tensor<2xf64>) -> tensor<2xcomplex<f64>>
// %result: [(1.0, 2.0), (3.0, 4.0)]
복합
시맨틱
다른 StableHLO 작업으로 구성된 (구성된) 작업을 캡슐화합니다.
inputs
및 composite_attributes
를 가져와서 results
를 생성합니다. 이
작업의 의미 체계는 decomposition
속성으로 구현됩니다. 이
프로그램을 변경하지 않고 composite
작업을 분해로 대체할 수 있음
의미합니다 분해를 인라인 처리해도 동일한 결과를 제공하지 않는 경우
연산의 의미를 사용하므로 custom_call
를 사용하는 것이 좋습니다.
version
필드 (기본값 0
)는 복합 요소의
의미론이 변경됩니다.
입력
라벨 | 이름 | 유형 |
---|---|---|
(I1) | inputs |
값의 가변수 |
(I2) | name |
string 유형의 상수 |
(I3) | composite_attributes |
속성 사전 |
(I4) | decomposition |
string 유형의 상수 |
(I5) | version |
si32 유형의 상수 |
출력
이름 | 유형 |
---|---|
results |
값의 가변수 |
제약조건
- (C1)
is_namespaced_op_name(name)
- (C2)
is_defined_in_parent_scope(decomposition)
- (C3)
types(inputs...) == input_types(decomposition)
- (C4)
types(results...) == output_types(decomposition)
예
%results = "stablehlo.composite"(%input0, %input1) {
name = "my_namespace.my_op",
composite_attributes = {
my_attribute = "my_value"
},
decomposition = @my_op,
version = 1 : i32
} : (tensor<f32>, tensor<f32>) -> tensor<f32>
이어붙이기
시맨틱
지정된 순서대로 dimension
측정기준을 따라 inputs
를 연결합니다.
인수를 생성하고 result
텐서를 생성합니다. 더 공식적으로
result[i0, ..., id, ..., iR-1] = inputs[k][i0, ..., kd, ..., iR-1]
, 각 항목의 의미는 다음과 같습니다.
id = d0 + ... + dk-1 + kd
.d
은(는)dimension
과(와) 같으며,d0
은(는)d
번째 크기입니다. 총inputs
페이지입니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | inputs |
텐서의 가변 수 또는 텐서당 양자화 텐서 | (C1~C6) |
(I2) | dimension |
si64 유형의 상수 |
(C2), (C4), (C6) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서 또는 텐서당 양자화 텐서 | (C5~C6) |
제약조건
- (C1)
same(element_type(inputs...))
. - (C2)
dim(inputs..., dimension)
를 제외한same(shape(inputs...))
입니다. - (C3)
0 < size(inputs)
. - (C4)
0 <= dimension < rank(inputs[0])
. - (C5)
element_type(result) = element_type(inputs[0])
. - (C6) 다음을 제외한
shape(result) = shape(inputs[0])
: <ph type="x-smartling-placeholder">- </ph>
dim(result, dimension) = dim(inputs[0], dimension) + ...
.
예
// %input0: [[1, 2], [3, 4], [5, 6]]
// %input1: [[7, 8]]
%result = "stablehlo.concatenate"(%input0, %input1) {
dimension = 0 : i64
} : (tensor<3x2xi64>, tensor<1x2xi64>) -> tensor<4x2xi64>
// %result: [[1, 2], [3, 4], [5, 6], [7, 8]]
상수
시맨틱
상수 value
에서 output
텐서를 생성합니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | value |
상수 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
output |
양자화 텐서 | (C1) |
제약조건
- (C1)
type(value) = type(output)
.
예
%output = "stablehlo.constant"() {
value = dense<[[0.0, 1.0], [2.0, 3.0]]> : tensor<2x2xf32>
} : () -> tensor<2x2xf32>
// %output: [[0.0, 1.0], [2.0, 3.0]]
전환
시맨틱
다음에서 한 요소 유형에서 다른 요소 유형으로 요소별 변환 수행
operand
텐서를 생성하고 result
텐서를 생성합니다.
boolean-to-any-supported-type 변환의 경우 false
값은 다음과 같습니다.
0으로 변환되고 true
값은 1로 변환됩니다. 대상
any-supported-type-to-boolean 변환 시 0 값은
false
이고 0이 아닌 값은 true
로 변환됩니다. 방법은 아래를 참조하세요.
복잡한 유형에서
사용할 수 있습니다
integer-to-integer, integer-to-floating-point 관련 변환의 경우 또는 floating-point-to-floating-point(소스 값이 정확하게 표시되는 경우 결과 값은 나타냅니다. 그 외의 경우에는 동작은 미정입니다. (#180)
floating-point-to-integer와 관련된 변환의 경우 소수 부분은 잘립니다. 잘린 값을 대상 유형에 표시할 수 없는 경우 동작은 미정입니다 (#180).
복소수에서 복잡도를 포함하는 변환은 floating-point-to-floating-point 변환을 사용하여 생성합니다.
complex-to-any-other-type 및 any-other-type-to-complex 전환의 경우 소스 허수 값이 무시되거나 대상 허수 값이 각각 0으로 설정되어 있습니다. 실제 부분의 변환은 부동 소수점 변환입니다.
원칙적으로 이 연산은 역양자화(
양자화 텐서에서 일반 텐서로, 양자화 (일반에서
양자화 텐서로 변환) 및 재양자화 (양자화 텐서 간의 변환)를
텐서) 중 하나)이지만 현재 전용 작업이 있습니다.
uniform_dequantize
및 uniform_quantize
두 번째, 세 번째 사용 사례입니다 향후에는 이 두 작업이 병합될 수 있음
convert
로 변환합니다. (#1576)
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서 | (C1) |
제약조건
- (C1)
shape(operand) = shape(result)
.
예
// %operand: [-1, 0, 1]
%result = "stablehlo.convert"(%operand) : (tensor<3xi64>) -> tensor<3xcomplex<f64>>
// %result: [(-1.0, 0.0), (0.0, 0.0), (1.0, 0.0)]
컨볼루션
시맨틱
lhs
의 윈도우와 rhs
의 슬라이스 사이의 내적을 계산하고 생성합니다.
result
입니다. 다음 다이어그램은 result
의 요소가 다음에서 계산되는 방식을 보여줍니다.
구체적인 예를 사용하여 lhs
및 rhs
를 실행합니다.
좀 더 공식적으로 lhs
의 관점에서 다음과 같이 입력을 재구성해 보세요.
lhs
의 윈도우를 표현할 수 있도록 하려면 다음을 실행하세요.
lhs_window_dimensions = lhs_shape(dim(lhs, input_batch_dimension), dim(rhs, kernel_spatial_dimensions), dim(lhs, input_feature_dimension))
.lhs_window_strides = lhs_shape(1, window_strides, 1)
.lhs_padding = lhs_shape([0, 0], padding, [0, 0])
.lhs_base_dilations = lhs_shape(1, lhs_dilation, 1)
.lhs_window_dilations = lhs_shape(1, rhs_dilation, 1)
.
이 프레임 조정에는 다음과 같은 도우미 함수가 사용됩니다.
lhs_shape(n, hw, c) = permute([n] + hw + [c], [input_batch_dimension] + input_spatial_dimensions + [input_feature_dimension])
.result_shape(n1, hw, c1) = permute([n1] + hw + [c1], [output_batch_dimension] + output_spatial_dimensions + [output_feature_dimension])
.permute([j0, j1, ..., jR-1], permutation) = [i0, i1, ..., iR-1]
, 여기서j[d] = i[permutation[d]]
.
feature_group_count = 1
및 batch_group_count = 1
인 경우 모든 경우에 대해
index_space(dim(result, output_spatial_dimensions...))
output_spatial_index
,
result[result_shape(:, output_spatial_index, :)] = dot_product
각 항목의 의미는 다음과 같습니다.
padding_value = constant(0, element_type(lhs))
.padded_lhs = pad(lhs, padding_value, lhs_padding[:, 0], lhs_padding[:, 1], lhs_base_dilations - 1)
.lhs_window_start = lhs_shape(0, output_spatial_index, 0) * lhs_window_strides
.lhs_window = slice(padded_lhs, lhs_window_start, lhs_window_start + lhs_window_dimensions, lhs_window_dilations)
.reversed_lhs_window = reverse(lhs_window, [input_spatial_dimensions[dim] for dim in range(size(window_reversal)) if window_reversal[dim] = true])
이 기능은 사용하지 않는 것으로 보이며 향후 삭제될 예정입니다. (#1181)dot_product = dot_general(reversed_lhs_window, rhs, lhs_batching_dimensions=[], lhs_contracting_dimensions=input_spatial_dimensions + [input_feature_dimension], rhs_batching_dimensions=[], rhs_contracting_dimensions=kernel_spatial_dimensions + [kernel_input_feature_dimension])
.
feature_group_count > 1
인 경우:
lhses = split(lhs, feature_group_count, input_feature_dimension)
.rhses = split(rhs, feature_group_count, kernel_output_feature_dimension)
.results... = convolution(lhses..., rhses..., ..., feature_group_count=1, ...)
.result = concatenate(results, output_feature_dimension)
.
batch_group_count > 1
인 경우:
lhses = split(lhs, batch_group_count, input_batch_dimension)
.rhses = split(rhs, batch_group_count, kernel_output_feature_dimension)
.results... = convolution(lhses..., rhses..., ..., batch_group_count=1, ...)
.result = concatenate(results, output_feature_dimension)
양자화 유형의 경우 dequantize_op_quantize(
lambda lhs, rhs: convolution(lhs, rhs, window_strides, padding,
lhs_dilation, rhs_dilation, window_reversal, input_batch_dimension,
input_feature_dimension, input_spatial_dimensions,
kernel_input_feature_dimension, kernel_output_feature_dimension,
kernel_spatial_dimensions, output_batch_dimension,
output_feature_dimension, output_spatial_dimensions,
feature_group_count, batch_group_count, precision_config), lhs, rhs,
type(result))
를 실행합니다.
하이브리드 양자화 유형의 경우 hybrid_dequantize_then_op(
lambda lhs, rhs: convolution(lhs, rhs, window_strides, padding,
lhs_dilation, rhs_dilation, window_reversal, input_batch_dimension,
input_feature_dimension, input_spatial_dimensions,
kernel_input_feature_dimension, kernel_output_feature_dimension,
kernel_spatial_dimensions, output_batch_dimension,
output_feature_dimension, output_spatial_dimensions,
feature_group_count, batch_group_count, precision_config), lhs, rhs)
를 수행합니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | lhs |
텐서 또는 텐서당 양자화 텐서 | (C1), (C10-C11), (C14) (C25), (C27-C28), (C31-C32), (C34) |
(I2) | rhs |
양자화 텐서 | (C1), (C14-C16), (C25), (C27-C29), (C31-C34) |
(I3) | window_strides |
si64 유형의 1차원 텐서 상수 |
(C2-C3), (C25) |
(I4) | padding |
si64 유형의 2차원 텐서 상수 |
(C4), (C25) |
(I5) | lhs_dilation |
si64 유형의 1차원 텐서 상수 |
(C5~C6), (C25) |
(I6) | rhs_dilation |
si64 유형의 1차원 텐서 상수 |
(C7~C8), (C25) |
(I7) | window_reversal |
i1 유형의 1차원 텐서 상수 |
(C9) |
(I8) | input_batch_dimension |
si64 유형의 상수 |
(C10), (C13), (C25) |
(I9) | input_feature_dimension |
si64 유형의 상수 |
(C11), (C13~C14) |
(I10) | input_spatial_dimensions |
si64 유형의 1차원 텐서 상수 |
(C12), (C13), (C25) |
(I11) | kernel_input_feature_dimension |
si64 유형의 상수 |
(C14), (C18) |
(I12) | kernel_output_feature_dimension |
si64 유형의 상수 |
(C15-C16), (C18), (C25), (C29) |
(I13) | kernel_spatial_dimensions |
si64 유형의 1차원 텐서 상수 |
(C17~C18), (C25) |
(I14) | output_batch_dimension |
si64 유형의 상수 |
(C20), (C25) |
(I15) | output_feature_dimension |
si64 유형의 상수 |
(C20), (C25), (C30) |
(I16) | output_spatial_dimensions |
si64 유형의 1차원 텐서 상수 |
(C19~C20), (C25) |
(I17) | feature_group_count |
si64 유형의 상수 |
(C11), (C14), (C16), (C21), (C23) |
(I18) | batch_group_count |
si64 유형의 상수 |
(C10), (C15), (C22), (C23), (C25) |
(I19) | precision_config |
DEFAULT , HIGH , HIGHEST 의 다양한 enum 수 |
(C24) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
양자화 텐서 | (C25-C28), (C30), (C32-34) |
제약조건
- (C1)
N = rank(lhs) = rank(rhs)
. - (C2)
size(window_strides) = N - 2
. - (C3)
0 < window_strides
. - (C4)
shape(padding) = [N - 2, 2]
. - (C5)
size(lhs_dilation) = N - 2
. - (C6)
0 < lhs_dilation
. - (C7)
size(rhs_dilation) = N - 2
. - (C8)
0 < rhs_dilation
. - (C9)
size(window_reversal) = N - 2
. - (C10)
dim(lhs, input_batch_dimension) % batch_group_count = 0
입니다. - (C11)
dim(lhs, input_feature_dimension) % feature_group_count = 0
입니다. - (C12)
size(input_spatial_dimensions) = N - 2
. - (C13) 주어진
input_dimensions = [input_batch_dimension] + input_spatial_dimensions + [input_feature_dimension]
: <ph type="x-smartling-placeholder">- </ph>
is_unique(input_dimensions)
.0 <= input_dimensions < N
.
- (C14)
dim(rhs, kernel_input_feature_dimension) = dim(lhs, input_feature_dimension) / feature_group_count
입니다. - (C15)
dim(rhs, kernel_output_feature_dimension) % batch_group_count = 0
입니다. - (C16)
dim(rhs, kernel_output_feature_dimension) % feature_group_count = 0
입니다. - (C17)
size(kernel_spatial_dimensions) = N - 2
). - (C18) 주어진
kernel_dimensions = kernel_spatial_dimensions + [kernel_input_feature_dimension] + [kernel_output_feature_dimension]
: <ph type="x-smartling-placeholder">- </ph>
is_unique(kernel_dimensions)
.0 <= kernel_dimensions < N
.
- (C19)
size(output_spatial_dimensions) = N - 2
). - (C20) 주어진
output_dimensions = [output_batch_dimension] + output_spatial_dimensions + [output_feature_dimension]
: <ph type="x-smartling-placeholder">- </ph>
is_unique(output_dimensions)
.0 <= output_dimensions < N
.
- (C21)
0 < feature_group_count
입니다. - (C22)
0 < batch_group_count
. - (C23)
feature_group_count = 1 or batch_group_count = 1
입니다. - (C24)
size(precision_config) = 2
입니다. - (C25)
dim(result, result_dim)
는 다음과 같이 정의됩니다. <ph type="x-smartling-placeholder">- </ph>
result_dim = output_batch_dimension
인 경우dim(lhs, input_batch_dimension) / batch_group_count
입니다.result_dim = output_feature_dimension
인 경우dim(rhs, kernel_output_feature_dimension)
입니다.- 그렇지 않은 경우
num_windows
, 각 항목의 의미는 다음과 같습니다. output_spatial_dimensions[spatial_dim] = result_dim
.lhs_dim = input_spatial_dimensions[spatial_dim]
.rhs_dim = kernel_spatial_dimensions[spatial_dim]
.dilated_input_shape[lhs_dim] = dim(lhs, lhs_dim) = 0 ? 0 : (dim(lhs, lhs_dim) - 1) * lhs_dilation[spatial_dim] + 1
.padded_input_shape[lhs_dim] = padding[spatial_dim, 0] + dilated_input_shape[lhs_dim] + padding[spatial_dim, 1]
.dilated_window_shape[lhs_dim] = dim(rhs, rhs_dim) = 0 ? 0 : (dim(rhs, rhs_dim) - 1) * rhs_dilation[spatial_dim] + 1
.is_empty_window[lhs_dim] = padded_input_shape[lhs_dim] = 0 || dilated_window_shape[lhs_dim] > padded_input_shape[lhs_dim]
.num_windows = is_empty_window[lhs_dim] ? 0 : floor((padded_input_shape[lhs_dim] - dilated_window_shape[lhs_dim]) / window_strides[spatial_dim]) + 1
.
- (C26)
rank(result) = N
입니다. - 작업이 양자화되지 않은 텐서를 사용하는 경우:
<ph type="x-smartling-placeholder">
- </ph>
- (C27)
element_type(lhs) = element_type(rhs) = element_type(result)
입니다.
- (C27)
- 연산이 양자화 텐서를 사용하는 경우:
<ph type="x-smartling-placeholder">
- </ph>
- (C28)
is_quantized(lhs) = is_quantized(result) and is_quantized(rhs)
입니다. - (C29)
is_per_axis_quantized(rhs)
인 경우, 그리고quantization_dimension(rhs) = kernel_output_feature_dimension
. - (C30)
is_per_axis_quantized(result)
인 경우,quantization_dimension(result) = output_feature_dimension
is_quantized(lhs)
인 경우:- (C31)
storage_type(lhs) = storage_type(rhs)
입니다. - (C32)
expressed_type(lhs) = expressed_type(rhs) = expressed_type(result)
입니다. - (C33)
is_per_tensor_quantized(rhs)
인 경우,is_per_tensor_quantized(result)
!is_quantized(lhs)
인 경우:- (C34)
element_type(lhs) = expressed_type(rhs) = element_type(result)
입니다.
- (C28)
예
// %lhs: [[
// [
// [1], [2], [5], [6]
// ],
// [
// [3], [4], [7], [8]
// ],
// [
// [10], [11], [14], [15]
// ],
// [
// [12], [13], [16], [17]
// ]
// ]]
//
// %rhs: [
// [[[1]], [[1]], [[1]]],
// [[[1]], [[1]], [[1]]],
// [[[1]], [[1]], [[1]]]
// ]
%result = "stablehlo.convolution"(%lhs, %rhs) {
window_strides = array<i64: 4, 4>,
padding = dense<0> : tensor<2x2xi64>,
lhs_dilation = array<i64: 2, 2>,
rhs_dilation = array<i64: 1, 1>,
window_reversal = array<i1: false, false>,
// In the StableHLO dialect, dimension numbers are encoded via:
// `[<input dimensions>]x[<kernel dimensions>]->[output dimensions]`.
// "b" is batch dimension, "f" is feature dimension,
// "i" is input feature dimension, "o" is output feature dimension,
// "0/1/etc" are spatial dimensions.
dimension_numbers = #stablehlo.conv<[b, 0, 1, f]x[0, 1, i, o]->[b, 0, 1, f]>,
batch_group_count = 1 : i64,
feature_group_count = 1 : i64,
precision_config = [#stablehlo<precision DEFAULT>, #stablehlo<precision DEFAULT>]
} : (tensor<1x4x4x1xi64>, tensor<3x3x1x1xi64>) -> tensor<1x2x2x1xi64>
// %result: [[
// [[10], [26]],
// [[46], [62]]
// ]]
코사인
시맨틱
operand
텐서에서 요소별 코사인 연산을 실행하고 다음을 생성합니다.
result
텐서. 요소 유형에 따라 다음 작업을 실행합니다.
- 부동 소수점 수: IEEE-754의
cos
- 복소수: 복소수 코사인
- 양자화 유형의 경우:
dequantize_op_quantize(cosine, operand, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// %operand: [
// [0.0, 1.57079632], // [0, pi/2]
// [3.14159265, 4.71238898] // [pi, 3pi/2]
// ]
%result = "stablehlo.cosine"(%operand) : (tensor<2x2xf32>) -> tensor<2x2xf32>
// %result: [[1.0, 0.0], [-1.0, 0.0]]
count_leading_zeros
시맨틱
operand
에서 선행 0비트 수의 요소별 카운트를 수행합니다.
텐서를 생성하고 result
텐서를 생성합니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
정수 유형의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
정수 유형의 텐서 | (C1) |
제약조건
- (C1)
type(operand) = type(result)
.
예
// %operand: [[0, 1], [128, -1]]
%result = "stablehlo.count_leading_zeros"(%operand) : (tensor<2x2xi64>) -> tensor<2x2xi64>
// %result: [[64, 63], [56, 0]]
custom_call
시맨틱
구현 정의 작업 call_target_name
를 캡슐화합니다.
inputs
및 called_computations
이고 results
를 생성합니다. has_side_effect
,
backend_config
및 api_version
은(는) 추가 정보를 제공하는 데 사용될 수 있습니다.
구현 정의 메타데이터입니다.
현재 이 작업에는 전혀 정리되지 않은 메타데이터의 하위 버전인 메타데이터의 XLA 컴파일러입니다. 향후 이 메타데이터를 통합할 계획입니다. (#741)
입력
라벨 | 이름 | 유형 |
---|---|---|
(I1) | inputs |
값의 가변수 |
(I2) | call_target_name |
string 유형의 상수 |
(I3) | has_side_effect |
i1 유형의 상수 |
(I4) | backend_config |
string 유형의 상수 또는 속성 사전 |
(I5) | api_version |
si32 유형의 상수 |
(I6) | called_computations |
string 유형 상수의 가변 수 |
출력
이름 | 유형 |
---|---|
results |
값의 가변수 |
예
%results = "stablehlo.custom_call"(%input0) {
call_target_name = "foo",
has_side_effect = false,
backend_config = {bar = 42 : i32},
api_version = 4 : i32,
called_computations = [@foo]
} : (tensor<f64>) -> tensor<f64>
나누기
시맨틱
피제수 lhs
및 제수 rhs
텐서의 요소별 나눗셈을 수행하고
result
텐서를 생성합니다. 요소 유형에 따라 다음 작업을 실행합니다.
- 정수: 어떤 값이든 대수적 몫을 생성하는 정수 나눗셈 소수 부분은 삭제되었습니다.
- 부동 소수점 수: IEEE-754의
division
- 복소수의 경우: 복소수 나눗셈.
- 양자화 유형의 경우:
<ph type="x-smartling-placeholder">
- </ph>
dequantize_op_quantize(divide, lhs, rhs, type(result))
.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | lhs |
정수, 부동 소수점, 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
(I2) | rhs |
정수, 부동 소수점, 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
정수, 부동 소수점, 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(lhs) = baseline_type(rhs) = baseline_type(result)
.
예
// %lhs: [17.1, -17.1, 17.1, -17.1]
// %rhs: [3.0, 3.0, -3.0, -3.0]
%result = "stablehlo.divide"(%lhs, %rhs) : (tensor<4xf32>, tensor<4xf32>) -> tensor<4xf32>
// %result: [5.66666651, -5.66666651, -5.66666651, 5.66666651]
dot_general
시맨틱
lhs
슬라이스와 rhs
슬라이스 사이의 내적을 계산하여 다음 값을 생성합니다.
result
텐서.
더 공식적으로 result[result_index] = dot_product
이며, 각 항목의 의미는 다음과 같습니다.
lhs_result_dimensions = [d for d in axes(lhs) and d not in lhs_batching_dimensions and d not in lhs_contracting_dimensions]
.rhs_result_dimensions = [d for d in axes(rhs) and d not in rhs_batching_dimensions and d not in rhs_contracting_dimensions]
.result_batching_index + result_lhs_index + result_rhs_index = result_index
여기서size(result_batching_index) = size(lhs_batching_dimensions)
,size(result_lhs_index) = size(lhs_result_dimensions)
및size(result_rhs_index) = size(rhs_result_dimensions)
입니다.transposed_lhs = transpose(lhs, lhs_batching_dimensions + lhs_result_dimensions + lhs_contracting_dimensions)
.transposed_lhs_slice = slice(transposed_lhs, result_batching_index + result_lhs_index + [:, ..., :])
.reshaped_lhs_slice = reshape(transposed_lhs_slice, dims(lhs, lhs_contracting_dimensions))
.transposed_rhs = transpose(rhs, rhs_batching_dimensions + rhs_result_dimensions + rhs_contracting_dimensions)
.transposed_rhs_slice = slice(transposed_rhs, result_batching_index + result_rhs_index + [:, ..., :])
.reshaped_rhs_slice = reshape(transposed_rhs_slice, dims(rhs, rhs_contracting_dimensions))
.dot_product = reduce( inputs=[multiply(reshaped_lhs_slice, reshaped_rhs_slice)], init_values=[constant(0, element_type(result))], dimensions=range(size(lhs_contracting_dimensions)), body=lambda x, y: add(x, y))
양자화 유형의 경우 dequantize_op_quantize(
lambda lhs, rhs: dot_general(lhs, rhs, lhs_batching_dimensions,
rhs_batching_dimensions, lhs_contracting_dimensions,
rhs_contracting_dimensions, precision_config), lhs, rhs, type(result))
를 실행합니다.
하이브리드 양자화 유형의 경우 hybrid_dequantize_then_op(
lambda lhs, rhs: dot_general(lhs, rhs, lhs_batching_dimensions,
rhs_batching_dimensions, lhs_contracting_dimensions,
rhs_contracting_dimensions, precision_config), lhs, rhs)
를 수행합니다.
precision_config
는 다음 조건의 속도와 정확성 간의 절충을 제어합니다.
가속기 백엔드에서 컴퓨팅 작업을 처리합니다 다음 중 하나일 수 있습니다(
이러한 열거형 값의 의미 체계는 과소 지정되어 있지만
이 문제를 해결할 계획인
#755)
DEFAULT
: 계산은 가장 빠르지만 근사치의 정확도가 가장 낮습니다. 원래 번호HIGH
: 계산 속도는 느리지만 원래 번호HIGHEST
: 계산은 가장 느리지만 원래 번호
DotAlgorithm
는 구현에 사용되는 알고리즘의 기본 속성을 정의합니다.
점 연산이며 정밀도도 정의합니다. 알고리즘 속성이
필드가 설정된 경우 precision_config
는 DEFAULT
여야 합니다. DotAlgorithms
는 기본 매개변수가 구현되므로 기본값이 없습니다.
정의할 수 있습니다 따라서 모든 점 알고리즘 필드를 None
로 설정하여
빈 점 알고리즘. 대신 precision_config
값을 사용합니다.
DotAlgorithm
필드는 다음과 같습니다.
lhs_precision_type
와rhs_precision_type
는 LHS와 연산의 RHS는 반올림됩니다. 정밀도 유형은 스토리지 유형을 정의합니다accumulation_type
: 축적에 사용되는 정밀도.lhs_component_count
님,rhs_component_count
님,num_primitive_operations
님 LHS 및/또는 RHS를 여러 개의 '원시' 작업을 수행하여 점 연산을 수행하여 값 - 일반적으로 더 높은 정밀도 (예: 정밀도가 높은 계산을 위해 bfloat16 인공지능 데이터 유형 활용: bf16_6x tf32_3x 등). 분해되지 않는 알고리즘의 경우 이러한 값은1
로 설정해야 합니다.allow_imprecise_accumulation
: 낮은 정밀도의 누적 여부를 지정합니다. 일부 단계에서는 허용됩니다 (예:CUBLASLT_MATMUL_DESC_FAST_ACCUM
).
DotAlgorithm
속성의 예:
// Inputs are casted to tf32, and then accumulated in f32:
{lhs_precision_type = tf32,
rhs_precision_type = tf32,
accumulation_type = f32,
lhs_component_count = 1,
rhs_component_count = 1,
num_primitive_operations = 1,
allow_imprecise_accumulation = false}
// bf16_6x: each input is decomposed to 3 bf16 components, then 6 dot operations are done on those components, and the result is accumulated in f32.
{lhs_precision_type = bf16,
rhs_precision_type = bf16,
accumulation_type = f32,
lhs_component_count = 3,
rhs_component_count = 3,
num_primitive_operations = 6,
allow_imprecise_accumulation = false}
// Inputs are (casted to) f8e5m2, and we accumulate in f32, but for some steps we may accumulate in lower precision.
{lhs_precision_type = f8e5m2,
rhs_precision_type = f8e5m2,
accumulation_type = f32,
lhs_component_count = 1,
rhs_component_count = 1,
num_primitive_operations = 1,
allow_imprecise_accumulation = true}
어떤 조합이 지원되는지 결정하는 것은 구현에 따라 다릅니다. 포함 일반적으로는 각 알고리즘이 각 네트워크에서 지원된다는 보장이 없습니다. StableHLO 소비자의 가속기 유형입니다. 주어진 알고리즘이 지원되는 경우 대안입니다. StableHLO 인증은 최상의 인증을 제공합니다 어떤 하드웨어에서도 지원되는 것으로 알려지지 않은 알고리즘을 방지합니다.
xla_data.proto > Algorithm
를 참고하세요.
몇 가지 지원되는 알고리즘 값을
확인할 수 있습니다 티켓 #2483은
백엔드에서 지원하는 알고리즘에 대한 중앙 집중식 문서입니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | lhs |
텐서 또는 텐서당 양자화 텐서 | (C5-C6), (C9-C10), (C12-C14), (C17-C18), (C20) |
(I2) | rhs |
양자화 텐서 | (C7~C10), (C12~C20) |
(I3) | lhs_batching_dimensions |
si64 유형의 1차원 텐서 상수 |
(C1), (C3), (C5), (C9), (C12) |
(I4) | rhs_batching_dimensions |
si64 유형의 1차원 텐서 상수 |
(C1), (C4), (C7), (C9) |
(I5) | lhs_contracting_dimensions |
si64 유형의 1차원 텐서 상수 |
(C2), (C3), (C6), (C10) |
(I6) | rhs_contracting_dimensions |
si64 유형의 1차원 텐서 상수 |
(C2), (C4), (C8), (C10), (C16) |
(I7) | precision_config |
DEFAULT , HIGH , HIGHEST 의 다양한 enum 수 |
(C11), (C21) |
(I8) | lhs_precision_type |
FloatType 또는 TensorFloat32 | (C21) |
(I9) | rhs_precision_type |
FloatType 또는 TensorFloat32 | (C21) |
(I10) | accumulation_type |
FloatType 또는 TensorFloat32 | (C21) |
(I11) | lhs_component_count |
si32 유형의 상수 |
(C21), (C22) |
(I12) | rhs_component_count |
si32 유형의 상수 |
(C21), (C23) |
(I13) | num_primitive_operations |
si32 유형의 상수 |
(C21), (C24) |
(I14) | allow_imprecise_accumulation |
bool 유형의 상수 |
(C21) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
양자화 텐서 | (C12), (C14), (C18-C20) |
제약조건
- (C1)
size(lhs_batching_dimensions) = size(rhs_batching_dimensions)
. - (C2)
size(lhs_contracting_dimensions) = size(rhs_contracting_dimensions)
. - (C3)
is_unique(lhs_batching_dimensions + lhs_contracting_dimensions)
. - (C4)
is_unique(rhs_batching_dimensions + rhs_contracting_dimensions)
. - (C5)
0 <= lhs_batching_dimensions < rank(lhs)
. - (C6)
0 <= lhs_contracting_dimensions < rank(lhs)
. - (C7)
0 <= rhs_batching_dimensions < rank(rhs)
. - (C8)
0 <= rhs_contracting_dimensions < rank(rhs)
. - (C9)
dim(lhs, lhs_batching_dimensions...) = dim(rhs, rhs_batching_dimensions...)
. - (C10)
dim(lhs, lhs_contracting_dimensions...) = dim(rhs, rhs_contracting_dimensions...)
입니다. - (C11)
size(precision_config) = 2
입니다. - (C12)
shape(result) = dim(lhs, lhs_batching_dimensions) + dim(lhs, lhs_result_dimensions) + dim(rhs, rhs_result_dimensions)
. - 작업이 양자화되지 않은 텐서를 사용하는 경우:
<ph type="x-smartling-placeholder">
- </ph>
- (C13)
element_type(lhs) = element_type(rhs)
입니다.
- (C13)
- 연산이 양자화 텐서를 사용하는 경우:
<ph type="x-smartling-placeholder">
- </ph>
- (C14)
is_quantized(lhs) = is_quantized(result) and is_quantized(rhs)
입니다. - (C15)
zero_points(rhs) = 0
입니다. - (C16)
is_per_axis_quantized(rhs)
인 경우,quantization_dimension(rhs)
이(가)rhs_contracting_dimensions
에 없습니다. is_quantized(lhs)
인 경우:- (C17)
storage_type(lhs) = storage_type(rhs)
). - (C18)
expressed_type(lhs) = expressed_type(rhs) = expressed_type(result)
입니다. - (C19)
is_per_tensor_quantized(rhs)
인 경우is_per_tensor_quantized(result)
!is_quantized(lhs)
인 경우:- (C20)
element_type(lhs) = expressed_type(rhs) = element_type(result)
입니다.
- (C14)
!is_empty_algorithm(lhs_precision_type, rhs_precision_type, accumulation_type, lhs_component_count, rhs_component_count, num_primitive_operations allow_imprecise_accumulation)
인 경우: <ph type="x-smartling-placeholder">- </ph>
- (C21)
precision_config... = DEFAULT
입니다. - (C22)
0 < lhs_component_count
. - (C23)
0 < rhs_component_count
입니다. - (C24)
0 < num_primitive_operations
입니다.
- (C21)
예
// %lhs: [
// [[1, 2],
// [3, 4]],
// [[5, 6],
// [7, 8]]
// ]
// %rhs: [
// [[1, 0],
// [0, 1]],
// [[1, 0],
// [0, 1]]
// ]
%result = "stablehlo.dot_general"(%lhs, %rhs) {
dot_dimension_numbers = #stablehlo.dot<
lhs_batching_dimensions = [0],
rhs_batching_dimensions = [0],
lhs_contracting_dimensions = [2],
rhs_contracting_dimensions = [1]
>,
precision_config = [#stablehlo<precision DEFAULT>, #stablehlo<precision DEFAULT>],
algorithm = #stablehlo.dot_algorithm<
lhs_precision_type = tf32,
rhs_precision_type = tf32,
accumulation_type = f32,
lhs_component_count = 1,
rhs_component_count = 1,
num_primitive_operations = 1,
allow_imprecise_accumulation = false
>
} : (tensor<2x2x2xi64>, tensor<2x2x2xi64>) -> tensor<2x2x2xi64>
// %result: [
// [[1, 2],
// [3, 4]],
// [[5, 6],
// [7, 8]]
// ]
dynamic_broadcast_in_dim
시맨틱
이 연산은 기능적으로 다음과 동일합니다.
broadcast_in_dim
연산을 수행하지만 결과 도형은 output_dimensions
를 통해 동적으로 지정됩니다.
이 작업은 선택적 속성인 known_expanding_dimensions
, known_non_expanding_dimensions
도 허용합니다.
를 사용합니다.
지정하지 않으면 모든 크기가 확장 가능한 것으로 간주됩니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
양자화 텐서 | (C1~C2), (C5~C6), (C9) |
(I2) | output_dimensions |
정수 유형의 1차원 텐서 | (C7) |
(I3) | broadcast_dimensions |
정수 유형의 1차원 상수 텐서 | (C2~C6) |
(I4) | known_expanding_dimensions |
정수 유형의 1차원 상수 텐서 | (C8~C9) |
(I5) | known_non_expanding_dimensions |
정수 유형의 1차원 상수 텐서 | (C8~C9) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
양자화 텐서 | (C1), (C3), (C5-C7) |
제약조건
- (C1)
element_type(result)
는 다음과 같이 주어집니다. <ph type="x-smartling-placeholder">- </ph>
!is_per_axis_quantized(operand)
인 경우element_type(operand)
입니다.- 다음
quantization_dimension(operand)
를 제외하고element_type(operand)
scales(operand)
,zero_points(operand)
은quantization_dimension(result)
,scales(result)
,zero_points(result)
resp.만 사용합니다.
- (C2)
size(broadcast_dimensions) = rank(operand)
. - (C3)
0 <= broadcast_dimensions < rank(result)
. - (C4)
is_unique(broadcast_dimensions)
. - (C5)
axes(operand)
의 모든d
의 경우: <ph type="x-smartling-placeholder">- </ph>
dim(operand, d) = 1
또는dim(operand, d) = dim(result, broadcast_dimensions[d])
.
- (C6)
is_per_axis_quantized(result)
인 경우: <ph type="x-smartling-placeholder">- </ph>
quantization_dimension(result) = broadcast_dimensions[quantization_dimension(operand)]
.dim(operand, quantization_dimension(operand)) = 1
인 경우scales(result)[i] = scales(operand)[0] and zero_points(result)[i] = zero_points(operand)[0] for i in range(dim(result, quantization_dimension(result)))
- (C7)
size(output_dimensions) = rank(result)
. - (C8)
is_unique(known_expanding_dimensions + known_non_expanding_dimensions)
. - (C9)
0 <= known_expanding_dimensions < rank(operand)
. - (C10)
0 <= known_non_expanding_dimensions < rank(operand)
입니다.
예
// %operand: [
// [1, 2, 3]
// ]
%operand = stablehlo.constant dense<[[1, 2, 3]]> : tensor<1x3xi64>
%output_dimensions = stablehlo.constant dense<[2, 3, 2]> : tensor<3xi64>
%result = "stablehlo.dynamic_broadcast_in_dim"(%operand, %output_dimensions) {
broadcast_dimensions = array<i64: 2, 1>,
known_expanding_dimensions = array<i64: 0>,
known_non_expanding_dimensions = array<i64: 1>
} : (tensor<1x3xi64>, tensor<3xi64>) -> tensor<2x3x2xi64>
// %result: [
// [
// [1, 1],
// [2, 2],
// [3, 3]
// ],
// [
// [1, 1],
// [2, 2],
// [3, 3]
// ]
// ]
dynamic_conv
시맨틱
이 연산은 기능적으로 다음과 동일합니다.
컨볼루션
연산이지만 패딩은 padding
를 통해 동적으로 지정됩니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | lhs |
텐서 또는 텐서당 양자화 텐서 | (C1), (C10-C11), (C14) (C25), (C26-C27), (C30-C31), (C33) |
(I2) | rhs |
양자화 텐서 | (C1), (C14-C16), (C26-C28), (C30-C33) |
(I3) | padding |
정수 유형의 2차원 텐서 | (C4) |
(I4) | window_strides |
si64 유형의 1차원 텐서 상수 |
(C2~C3) |
(I5) | lhs_dilation |
si64 유형의 1차원 텐서 상수 |
(C5~C6) |
(I6) | rhs_dilation |
si64 유형의 1차원 텐서 상수 |
(C7~C8) |
(I7) | window_reversal |
i1 유형의 1차원 텐서 상수 |
(C9) |
(I8) | input_batch_dimension |
si64 유형의 상수 |
(C10), (C13) |
(I9) | input_feature_dimension |
si64 유형의 상수 |
(C11), (C13~C14) |
(I10) | input_spatial_dimensions |
si64 유형의 1차원 텐서 상수 |
(C12), (C13) |
(I11) | kernel_input_feature_dimension |
si64 유형의 상수 |
(C14), (C18) |
(I12) | kernel_output_feature_dimension |
si64 유형의 상수 |
(C15-C16), (C18), (C28) |
(I13) | kernel_spatial_dimensions |
si64 유형의 1차원 텐서 상수 |
(C17~C18) |
(I14) | output_batch_dimension |
si64 유형의 상수 |
(C20) |
(I15) | output_feature_dimension |
si64 유형의 상수 |
(C20), (C29) |
(I16) | output_spatial_dimensions |
si64 유형의 1차원 텐서 상수 |
(C19~C20) |
(I17) | feature_group_count |
si64 유형의 상수 |
(C11), (C14), (C16), (C21), (C23) |
(I18) | batch_group_count |
si64 유형의 상수 |
(C10), (C15), (C22), (C23) |
(I19) | precision_config |
DEFAULT , HIGH , HIGHEST 의 다양한 enum 수 |
(C24) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
양자화 텐서 | (C25-C27), (C29), (C31-C33) |
제약조건
- (C1)
N = rank(lhs) = rank(rhs)
. - (C2)
size(window_strides) = N - 2
. - (C3)
0 < window_strides
. - (C4)
shape(padding) = [N - 2, 2]
. - (C5)
size(lhs_dilation) = N - 2
. - (C6)
0 < lhs_dilation
. - (C7)
size(rhs_dilation) = N - 2
. - (C8)
0 < rhs_dilation
. - (C9)
size(window_reversal) = N - 2
. - (C10)
dim(lhs, input_batch_dimension) % batch_group_count = 0
입니다. - (C11)
dim(lhs, input_feature_dimension) % feature_group_count = 0
입니다. - (C12)
size(input_spatial_dimensions) = N - 2
. - (C13) 주어진
input_dimensions = [input_batch_dimension] + input_spatial_dimensions + [input_feature_dimension]
: <ph type="x-smartling-placeholder">- </ph>
is_unique(input_dimensions)
.0 <= input_dimensions < N
.
- (C14)
dim(rhs, kernel_input_feature_dimension) = dim(lhs, input_feature_dimension) / feature_group_count
입니다. - (C15)
dim(rhs, kernel_output_feature_dimension) % batch_group_count = 0
입니다. - (C16)
dim(rhs, kernel_output_feature_dimension) % feature_group_count = 0
입니다. - (C17)
size(kernel_spatial_dimensions) = N - 2
). - (C18) 주어진
kernel_dimensions = kernel_spatial_dimensions + [kernel_input_feature_dimension] + [kernel_output_feature_dimension]
: <ph type="x-smartling-placeholder">- </ph>
is_unique(kernel_dimensions)
.0 <= kernel_dimensions < N
.
- (C19)
size(output_spatial_dimensions) = N - 2
). - (C20) 주어진
output_dimensions = [output_batch_dimension] + output_spatial_dimensions + [output_feature_dimension]
: <ph type="x-smartling-placeholder">- </ph>
is_unique(output_dimensions)
.0 <= output_dimensions < N
.
- (C21)
0 < feature_group_count
입니다. - (C22)
0 < batch_group_count
. - (C23)
feature_group_count = 1 or batch_group_count = 1
입니다. - (C24)
size(precision_config) = 2
입니다. - (C25)
dim(result, result_dim)
는 다음과 같이 정의됩니다. <ph type="x-smartling-placeholder">- </ph>
result_dim = output_batch_dimension
인 경우dim(lhs, input_batch_dimension) / batch_group_count
입니다.result_dim = output_feature_dimension
인 경우dim(rhs, kernel_output_feature_dimension)
입니다.- 그렇지 않은 경우
num_windows
, 각 항목의 의미는 다음과 같습니다. output_spatial_dimensions[spatial_dim] = result_dim
.lhs_dim = input_spatial_dimensions[spatial_dim]
.rhs_dim = kernel_spatial_dimensions[spatial_dim]
.dilated_input_shape[lhs_dim] = dim(lhs, lhs_dim) = 0 ? 0 : (dim(lhs, lhs_dim) - 1) * lhs_dilation[spatial_dim] + 1
.padded_input_shape[lhs_dim] = padding[spatial_dim, 0] + dilated_input_shape[lhs_dim] + padding[spatial_dim, 1]
.dilated_window_shape[lhs_dim] = dim(rhs, rhs_dim) = 0 ? 0 : (dim(rhs, rhs_dim) - 1) * rhs_dilation[spatial_dim] + 1
.is_empty_window[lhs_dim] = padded_input_shape[lhs_dim] = 0 || dilated_window_shape[lhs_dim] > padded_input_shape[lhs_dim]
.num_windows = is_empty_window[lhs_dim] ? 0 : floor((padded_input_shape[lhs_dim] - dilated_window_shape[lhs_dim]) / window_strides[spatial_dim]) + 1
.
- (C26)
rank(result) = N
입니다. - 작업이 양자화되지 않은 텐서를 사용하는 경우:
<ph type="x-smartling-placeholder">
- </ph>
- (C27)
element_type(lhs) = element_type(rhs) = element_type(result)
입니다.
- (C27)
- 연산이 양자화 텐서를 사용하는 경우:
<ph type="x-smartling-placeholder">
- </ph>
- (C28)
is_quantized(lhs) = is_quantized(result) and is_quantized(rhs)
입니다. - (C29)
is_per_axis_quantized(rhs)
인 경우, 그리고quantization_dimension(rhs) = kernel_output_feature_dimension
. - (C30)
is_per_axis_quantized(result)
인 경우,quantization_dimension(result) = output_feature_dimension
is_quantized(lhs)
인 경우:- (C31)
storage_type(lhs) = storage_type(rhs)
입니다. - (C32)
expressed_type(lhs) = expressed_type(rhs) = expressed_type(result)
입니다. - (C33)
is_per_tensor_quantized(rhs)
인 경우,is_per_tensor_quantized(result)
!is_quantized(lhs)
인 경우:- (C34)
element_type(lhs) = expressed_type(rhs) = element_type(result)
입니다.
- (C28)
예
// %lhs: [[
// [[1], [2], [5], [6]],
// [[3], [4], [7], [8]],
// [[10], [11], [14], [15]],
// [[12], [13], [16], [17]]
// ]]
//
// %rhs: [
// [[[1]], [[1]], [[1]]],
// [[[1]], [[1]], [[1]]],
// [[[1]], [[1]], [[1]]]
// ]
// %padding: [[1, 1],
// [1, 1]]
%result = "stablehlo.dynamic_conv"(%lhs, %rhs, %padding) {
window_strides = array<i64: 4, 4>,
lhs_dilation = array<i64: 2, 2>,
rhs_dilation = array<i64: 1, 1>,
window_reversal = array<i1: false, false>,
dimension_numbers = #stablehlo.conv<raw
input_batch_dimension = 0,
input_feature_dimension = 3,
input_spatial_dimensions = [0, 1],
kernel_input_feature_dimension = 2,
kernel_output_feature_dimension = 3,
kernel_spatial_dimensions = [0, 1],
output_batch_dimension = 0,
output_feature_dimension = 3,
output_spatial_dimensions = [1, 2]
>,
feature_group_count = 1 : i64,
batch_group_count = 1 : i64,
precision_config = [#stablehlo<precision DEFAULT>, #stablehlo<precision DEFAULT>]
} : (tensor<1x4x4x1xi64>, tensor<3x3x1x1xi64>, tensor<2x2xi64>) -> tensor<1x2x2x1xi64>
// %result: [[
// [[1], [5]],
// [[10], [14]]
// ]]
dynamic_gather
시맨틱
이 연산은 기능적으로 다음과 동일합니다.
수집
연산을 나타내며, slice_sizes
가 동적으로 값으로 지정됩니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
텐서 또는 텐서당 양자화 텐서 | (C1), (C7), (C10-C12), (C14) |
(I2) | start_indices |
정수 유형의 텐서 | (C2), (C3), (C13) |
(I3) | slice_sizes |
정수 유형의 1차원 텐서 | (C8), (C11~C13) |
(I4) | offset_dims |
si64 유형의 1차원 텐서 상수 |
(C1), (C4-C5), (C13) |
(I5) | collapsed_slice_dims |
si64 유형의 1차원 텐서 상수 |
(C1), (C6-C8), (C13) |
(I6) | start_index_map |
si64 유형의 1차원 텐서 상수 |
(C3), (C9), (C10) |
(I7) | index_vector_dim |
si64 유형의 상수 |
(C2), (C3), (C13) |
(I8) | indices_are_sorted |
i1 유형의 상수 |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서 또는 텐서당 양자화 텐서 | (C5), (C13~C14) |
제약조건
- (C1)
rank(operand) = size(offset_dims) + size(collapsed_slice_dims)
. - (C2)
0 <= index_vector_dim <= rank(start_indices)
. - (C3)
size(start_index_map) = index_vector_dim < rank(start_indices) ? dim(start_indices, index_vector_dim) : 1
. - (C4)
is_unique(offset_dims) and is_sorted(offset_dims)
. - (C5)
0 <= offset_dims < rank(result)
. - (C6)
is_unique(collapsed_slice_dims) and is_sorted(collapsed_slice_dims)
. - (C7)
0 <= collapsed_slice_dims < rank(operand)
. - (C8)
slice_sizes[collapsed_slice_dims...] <= 1
. - (C9)
is_unique(start_index_map)
. - (C10)
0 <= start_index_map < rank(operand)
입니다. - (C11)
size(slice_sizes) = rank(operand)
입니다. - (C12)
0 <= slice_sizes <= shape(operand)
. - (C13)
shape(result) = combine(batch_dim_sizes, offset_dim_sizes)
, 각 항목의 의미는 다음과 같습니다. <ph type="x-smartling-placeholder">- </ph>
batch_dim_sizes = shape(start_indices)
(다음 크기:index_vector_dim
에 해당하는start_indices
은(는) 포함되지 않습니다.offset_dim_sizes = shape(slice_sizes)
, 다음과 같은 예외가 있습니다.collapsed_slice_dims
에 해당하는slice_sizes
에 포함되지 않습니다.combine
는batch_dims
에 해당하는 축에batch_dim_sizes
를 배치합니다.offset_dims
에 해당하는 축에서offset_dim_sizes
입니다.
- (C14)
element_type(operand) = element_type(result)
입니다.
예
// %operand: [
// [[1, 2], [3, 4], [5, 6], [7, 8]],
// [[9, 10],[11, 12], [13, 14], [15, 16]],
// [[17, 18], [19, 20], [21, 22], [23, 24]]
// ]
// %start_indices: [
// [[0, 0], [1, 0], [2, 1]],
// [[0, 1], [1, 1], [0, 2]]
// ]
// %slize_sizes: [1, 2, 2]
%result = "stablehlo.dynamic_gather"(%operand, %start_indices, %slize_sizes) {
dimension_numbers = #stablehlo.gather<
offset_dims = [2, 3],
collapsed_slice_dims = [0],
start_index_map = [1, 0],
index_vector_dim = 2>,
indices_are_sorted = false
} : (tensor<3x4x2xi64>, tensor<2x3x2xi64>, tensor<3xi64>) -> tensor<2x3x2x2xi64>
// %result: [
// [
// [[1, 2], [3, 4]],
// [[3, 4], [5, 6]],
// [[13, 14], [15, 16]]
// ],
// [
// [[9, 10], [11, 12]],
// [[11, 12], [13, 14]],
// [[17, 18], [19, 20]]
// ]
// ]
dynamic_iota
시맨틱
이 연산은 기능적으로 다음과 동일합니다.
iota
연산을 수행하지만 결과 도형은 output_shape
를 통해 동적으로 지정됩니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | output_shape |
정수 유형의 1차원 텐서 | (C1), (C2) |
(I2) | iota_dimension |
si64 |
(C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
정수, 부동 소수점, 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C2) |
제약조건
- (C1)
0 <= iota_dimension < size(output_shape)
. - (C2)
rank(result) = size(output_shape)
.
예
%output_shape = stablehlo.constant dense<[4, 5]> : tensor<2xi64>
%result = "stablehlo.dynamic_iota"(%output_shape) {
iota_dimension = 0 : i64
} : (tensor<2xi64>) -> tensor<4x5xi64>
// %result: [
// [0, 0, 0, 0, 0],
// [1, 1, 1, 1, 1],
// [2, 2, 2, 2, 2],
// [3, 3, 3, 3, 3]
// ]
dynamic_pad
시맨틱
이 연산은 기능적으로 다음과 동일합니다.
패드
작업이지만 edge_padding_low
, edge_padding_high
, interior_padding
사용
동적으로 지정됩니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
텐서 또는 텐서당 양자화 텐서 | (C1), (C2), (C4) |
(I2) | padding_value |
0차원 텐서 또는 텐서당 양자화 텐서 | (C1) |
(I3) | edge_padding_low |
정수 유형의 1차원 텐서 | (C1), (C4) |
(I4) | edge_padding_high |
정수 유형의 1차원 텐서 | (C1), (C4) |
(I5) | interior_padding |
정수 유형의 1차원 텐서 | (C2~C4) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서 또는 텐서당 양자화 텐서 | (C3~C6) |
제약조건
- (C1)
element_type(operand) = element_type(padding_value) = element_type(result)
. - (C2)
size(edge_padding_low) = size(edge_padding_high) = size(interior_padding) = rank(operand)
. - (C3)
0 <= interior_padding
. - (C4)
shape(result) = shape(operand) + edge_padding_low + max(shape(operand) - 1, 0) * interior_padding + edge_padding_high
.
예
// %operand: [
// [1, 2, 3],
// [4, 5, 6]
// ]
// %padding_value: 0
// %edge_padding_low: [0, 1]
// %edge_padding_high: [2, 1]
// %interior_padding: [1, 2]
%result = "stablehlo.dynamic_pad"(%operand, %padding_value,
%edge_padding_low, %edge_padding_high, %interior_padding
) : (tensor<2x3xi64>, tensor<i64>, tensor<2xi64>, tensor<2xi64>, tensor<2xi64>) -> tensor<5x9xi64>
// %result: [
// [0, 1, 0, 0, 2, 0, 0, 3, 0],
// [0, 0, 0, 0, 0, 0, 0, 0, 0],
// [0, 4, 0, 0, 5, 0, 0, 6, 0],
// [0, 0, 0, 0, 0, 0, 0, 0, 0],
// [0, 0, 0, 0, 0, 0, 0, 0, 0]
// ]
dynamic_reshape
시맨틱
이 연산은 기능적으로 다음과 동일합니다.
재형성(reshape)
연산을 수행하지만 결과 도형은 output_shape
를 통해 동적으로 지정됩니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
양자화 텐서 | (C1~C3) |
(I2) | output_shape |
정수 유형의 1차원 텐서 | (C4) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
양자화 텐서 | (C1~C4) |
제약조건
- (C1)
element_type(result)
는 다음과 같이 주어집니다. <ph type="x-smartling-placeholder">- </ph>
!is_per_axis_quantized(operand)
인 경우element_type(operand)
입니다.quantization_dimension(operand)
및 다음을 제외하고element_type(operand)
quantization_dimension(result)
는 다를 수 있습니다.
- (C2)
size(operand) = size(result)
. - (C3)
is_per_axis_quantized(operand)
인 경우: <ph type="x-smartling-placeholder">- </ph>
reduce(dims(operand, [0, 1, ..., quantization_dimension(operand) - 1]), init_values=1, dimensions=[0], body=lambda x, y: x * y) = reduce(dims(result, [0, 1, ..., quantization_dimension(result) - 1]), init_values=1, dimensions=[0], body=lambda x, y: x * y)
.dim(operand, quantization_dimension(operand)) = dim(result, quantization_dimension(result))
.reduce(dims(operand, [quantization_dimension(operand) + 1, ..., rank(operand) - 1]), init_values=1, dimensions=[0], body=lambda x, y: x * y) = reduce(dims(result, [quantization_dimension(result) + 1, ..., rank(result) - 1]), init_values=1, dimensions=[0], body=lambda x, y: x * y)
.
- (C4)
size(output_shape) = rank(result)
.
예
// %operand: [[1, 2, 3], [4, 5, 6]]
// %output_shape: [3, 2]
%result = "stablehlo.dynamic_reshape"(%operand, %output_shape) : (tensor<2x3xi64>, tensor<2xi64>) -> tensor<3x2xi64>
// %result: [[1, 2], [3, 4], [5, 6]]
dynamic_slice
시맨틱
동적으로 계산된 시작 색인을 사용하여 operand
에서 슬라이스를 추출합니다.
result
텐서를 생성합니다. start_indices
에는 다음의 시작 색인이 포함됩니다.
잠재적 조정이 적용되는 각 측정기준의 슬라이스 및 slice_sizes
각 차원에 대한 슬라이스의 크기를 포함합니다. 더 공식적으로
result[result_index] = operand[operand_index]
각 항목의 의미는 다음과 같습니다.
adjusted_start_indices = clamp(0, start_indices, shape(operand) - slice_sizes)
.operand_index = adjusted_start_indices + result_index
.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
텐서 또는 텐서당 양자화 텐서 | (C1), (C2), (C4) |
(I2) | start_indices |
정수 유형의 0차원 텐서의 가변 수 | (C2), (C3) |
(I3) | slice_sizes |
si64 유형의 1차원 텐서 상수 |
(C2), (C4), (C5) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서 또는 텐서당 양자화 텐서 | (C1), (C5) |
제약조건
- (C1)
element_type(operand) = element_type(result)
. - (C2)
size(start_indices) = size(slice_sizes) = rank(operand)
. - (C3)
same(type(start_indices...))
. - (C4)
0 <= slice_sizes <= shape(operand)
. - (C5)
shape(result) = slice_sizes
.
예
// %operand: [
// [0, 0, 1, 1],
// [0, 0, 1, 1],
// [0, 0, 0, 0],
// [0, 0, 0, 0]
// ]
// %start_indices0: -1
// %start_indices1: 3
%result = "stablehlo.dynamic_slice"(%operand, %start_indices0, %start_indices1) {
slice_sizes = array<i64: 2, 2>
} : (tensor<4x4xi32>, tensor<i64>, tensor<i64>) -> tensor<2x2xi32>
// %result: [
// [1, 1],
// [1, 1]
// ]
dynamic_update_slice
시맨틱
다음을 제외하면 operand
텐서와 동일한 result
텐서를 생성합니다.
start_indices
에서 시작하는 슬라이스가 update
의 값으로 업데이트됩니다.
더 공식적으로 result[result_index]
는 다음과 같이 정의됩니다.
0 <= update_index < shape(update)
인 경우update[update_index]
, 각 항목의 의미는 다음과 같습니다. <ph type="x-smartling-placeholder">- </ph>
adjusted_start_indices = clamp(0, start_indices, shape(operand) - shape(update))
.update_index = result_index - adjusted_start_indices
.
- 그 외에는
operand[result_index]
입니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
텐서 또는 텐서당 양자화 텐서 | (C1~C4), (C6) |
(I2) | update |
텐서 또는 텐서당 양자화 텐서 | (C2), (C3), (C6) |
(I3) | start_indices |
정수 유형의 0차원 텐서의 가변 수 | (C4), (C5) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서 또는 텐서당 양자화 텐서 | (C1) |
제약조건
- (C1)
type(operand) = type(result)
. - (C2)
element_type(update) = element_type(operand)
. - (C3)
rank(update) = rank(operand)
. - (C4)
size(start_indices) = rank(operand)
. - (C5)
same(type(start_indices...))
. - (C6)
0 <= shape(update) <= shape(operand)
.
예
// %operand: [
// [1, 1, 0, 0],
// [1, 1, 0, 0],
// [1, 1, 1, 1],
// [1, 1, 1, 1]
// ]
// %update: [
// [1, 1],
// [1, 1]
// ]
// %start_indices0: -1
// %start_indices1: 3
%result = "stablehlo.dynamic_update_slice"(%operand, %update, %start_indices0, %start_indices1)
: (tensor<4x4xi32>, tensor<2x2xi32>, tensor<i64>, tensor<i64>) -> tensor<4x4xi32>
// %result: [
// [1, 1, 1, 1],
// [1, 1, 1, 1],
// [1, 1, 1, 1],
// [1, 1, 1, 1]
// ]
지수
시맨틱
operand
텐서에서 요소별 지수 연산을 실행하고 다음을 생성합니다.
result
텐서. 요소 유형에 따라 다음 작업을 실행합니다.
- 부동 소수점 수: IEEE-754의
exp
- 복소수의 경우: 복소수 지수입니다.
- 양자화 유형의 경우:
dequantize_op_quantize(exponential, operand, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// %operand: [[0.0, 1.0], [2.0, 3.0]]
%result = "stablehlo.exponential"(%operand) : (tensor<2x2xf64>) -> tensor<2x2xf64>
// %result: [[1.0, 2.7182818284590451], [7.3890560989306504, 20.085536923187668]]
exponential_minus_one
시맨틱
operand
텐서에서 요소별 지수에서 연산 1개를 뺀 값 실행
result
텐서를 생성합니다. 요소 유형에 따라 다음 작업을 실행합니다.
- 부동 소수점 수: IEEE-754의
expm1
- 복소수의 경우: 복소수 지수에서 1을 뺀 값입니다.
- 양자화 유형의 경우:
dequantize_op_quantize(exponential_minus_one, operand, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// %operand: [0.0, 1.0]
%result = "stablehlo.exponential_minus_one"(%operand) : (tensor<2xf64>) -> tensor<2xf64>
// %result: [0.0, 1.71828187]
fft
시맨틱
실제 복잡한 푸리에 대해 정방향 및 역 푸리에 변환 수행 두 가지 특성이 있습니다
fft_type
는 다음 중 하나입니다.
FFT
: 복소수에서 복잡한 FFT를 전달합니다.IFFT
: 복소수-복소수의 역 FFT입니다.RFFT
: 실수에서 복소수 FFT로 전달합니다.IRFFT
: 실숫값의 복소수 역 FFT입니다 (예: 복소수에서 실수를 반환).
더 공식적으로는 다음과 같은 1차원 텐서를 사용하는 fft
함수가 있다고 가정해 보겠습니다.
복잡한 유형을 입력으로 사용하여
이산 푸리에 변환을 계산합니다.
fft_type = FFT
의 경우 result
는 일련의 L의 최종 결과로 정의됩니다.
L = size(fft_length)
. 예를 들어 L = 3
의 경우는 다음과 같습니다.
result1[i0, ..., :] = fft(operand[i0, ..., :])
.result2[i0, ..., :, iR-1] = fft(result1[i0, ..., :, iR-1])
.result[i0, ..., :, iR-2, iR-1] = fft(result2[i0, ..., :, iR-2, iR-1])
.
또한 동일한 형식 시그니처를 갖는 ifft
함수가
다음과 같이 fft
의 역을 계산합니다.
fft_type = IFFT
의 경우 result
는 계산의 역으로 정의됩니다.
(fft_type = FFT
) 예를 들어 L = 3
의 경우는 다음과 같습니다.
result1[i0, ..., :, iR-2, iR-1] = ifft(operand[i0, ..., :, iR-2, iR-1])
.result2[i0, ..., :, iR-1] = ifft(result1[i0, ..., :, iR-1])
.result[i0, ..., :] = ifft(result2[i0, ..., :])
.
또한 다음과 같은 1차원 텐서를 사용하는 rfft
함수가 있다고 가정해 보겠습니다.
부동 소수점 유형은 다음과 같은 복잡한 유형의 1차원 텐서를 생성합니다.
동일한 부동 소수점 의미 체계를 사용하며 다음과 같이 작동합니다.
rfft(real_operand) = truncated_result
각 항목의 의미는 다음과 같습니다.complex_operand... = (real_operand..., 0.0)
.complex_result = fft(complex_operand)
.truncated_result = complex_result[:(rank(complex_result) / 2 + 1)]
.
(이산 푸리에 변환이 실제 피연산자에 대해 계산될 때는 첫 번째 피연산자가
결과의 N/2 + 1
요소가 결과의 나머지 부분을 명확하게 정의합니다.
따라서 중복 요소 계산을 방지하기 위해 rfft
의 결과가 잘립니다.
fft_type = RFFT
의 경우 result
는 일련의 L의 최종 결과로 정의됩니다.
L = size(fft_length)
. 예를 들어 L = 3
의 경우는 다음과 같습니다.
result1[i0, ..., :] = rfft(operand[i0, ..., :])
.result2[i0, ..., :, iR-1] = fft(result1[i0, ..., :, iR-1])
.result[i0, ..., :, iR-2, iR-1] = fft(result2[i0, ..., :, iR-2, iR-1])
.
마지막으로, irfft
함수에 같은 형식 서명과
다음과 같이 rfft
의 역을 계산합니다.
fft_type = IRFFT
의 경우 result
는 계산의 역으로 정의됩니다.
(fft_type = RFFT
) 예를 들어 L = 3
의 경우는 다음과 같습니다.
result1[i0, ..., :, iR-2, iR-1] = ifft(operand[i0, ..., :, iR-2, iR-1])
.result2[i0, ..., :, iR-1] = ifft(result1[i0, ..., :, iR-1])
.result[i0, ..., :] = irfft(result2[i0, ..., :])
.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 또는 복합 유형의 텐서 | (C1), (C2), (C4), (C5) |
(I2) | fft_type |
FFT , IFFT , RFFT , IRFFT 의 열거형 |
(C2), (C5) |
(I3) | fft_length |
si64 유형의 1차원 텐서 상수 |
(C1), (C3), (C4) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 또는 복합 유형의 텐서 | (C2), (C4), (C5) |
제약조건
- (C1)
size(fft_length) <= rank(operand)
. - (C2)
operand
요소 유형과result
요소 유형의 관계는 다음과 같이 다양합니다. <ph type="x-smartling-placeholder">- </ph>
fft_type = FFT
이면element_type(operand)
,element_type(result)
입니다. 동일한 복합 유형을 가질 수 있습니다fft_type = IFFT
이면element_type(operand)
,element_type(result)
입니다. 동일한 복합 유형을 가질 수 있습니다fft_type = RFFT
인 경우element_type(operand)
는 부동 소수점 유형이고element_type(result)
는 동일한 부동 소수점의 복합 유형입니다. 의미합니다fft_type = IRFFT
인 경우element_type(operand)
는 복합 유형이며element_type(result)
는 동일한 부동 소수점의 부동 소수점 유형입니다. 의미합니다
- (C3)
1 <= size(fft_length) <= 3
. - (C4)
operand
와result
사이에 다음 텐서의real
가 있습니다. 부동 소수점 유형을 선택한 다음shape(real)[-size(fft_length):] = fft_length
를 선택합니다. - (C5) 다음을 제외한
shape(result) = shape(operand)
: <ph type="x-smartling-placeholder">- </ph>
fft_type = RFFT
인 경우,dim(result, -1) = dim(operand, -1) = 0 ? 0 : dim(operand, -1) / 2 + 1
fft_type = IRFFT
인 경우,dim(operand, -1) = dim(result, -1) = 0 ? 0 : dim(result, -1) / 2 + 1
예
// %operand: [(1.0, 0.0), (0.0, 0.0), (0.0, 0.0), (0.0, 0.0)]
%result = "stablehlo.fft"(%operand) {
fft_type = #stablehlo<fft_type FFT>,
fft_length = array<i64: 4>
} : (tensor<4xcomplex<f32>>) -> tensor<4xcomplex<f32>>
// %result: [(1.0, 0.0), (1.0, 0.0), (1.0, 0.0), (1.0, 0.0)]
floor
시맨틱
operand
텐서의 요소별 하한선을 실행하고 result
텐서를 생성합니다.
IEEE-754에서 roundToIntegralTowardNegative
작업을 구현합니다.
지정할 수도 있습니다 양자화 유형의 경우
dequantize_op_quantize(floor, operand, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// %operand: [-0.8166, -0.2530, 0.2530, 0.8166, 2.0]
%result = "stablehlo.floor"(%operand) : (tensor<5xf32>) -> tensor<5xf32>
// %result: [-1.0, -1.0, 0.0, 0.0, 2.0]
수집
시맨틱
start_indices
에 지정된 오프셋에서 operand
텐서에서 슬라이스를 수집합니다.
result
텐서를 생성합니다.
다음 다이어그램은 result
의 요소가 다음 위치에 있는 요소에 매핑되는 방식을 보여줍니다.
구체적인 예를 사용하여 operand
이 다이어그램은 result
을(를) 보여주는 예입니다.
어떤 operand
색인에 해당하는지 자세히 설명합니다.
더 공식적으로 result[result_index] = operand[operand_index]
, 각 항목의 의미는 다음과 같습니다.
batch_dims = [d for d in axes(result) and d not in offset_dims]
.batch_index = result_index[batch_dims...]
.start_index
는 다음과 같이 정의됩니다. <ph type="x-smartling-placeholder">- </ph>
start_indices[bi0, ..., :, ..., biN]
, 여기서bi
는 다음의 개별 요소입니다. 다음과 같은 경우batch_index
및:
가index_vector_dim
색인에 삽입됩니다.index_vector_dim
미만rank(start_indices)
- 그 외에는
[start_indices[batch_index]]
입니다.
axes(operand)
의d_operand
에 대해 <ph type="x-smartling-placeholder">- </ph>
full_start_index[d_operand] = clamp(start_index[d_start], 0, dim(operand, d_operand) - slice_sizes[d_operand])
d_operand = start_index_map[d_start]
인 경우.- 그 외에는
full_start_index[d_operand] = 0
입니다.
axes(operand)
의d_operand
에 대해 <ph type="x-smartling-placeholder">- </ph>
full_batching_index[d_operand] = batch_index[d_start - (d_start < index_vector_dim ? 0 : 1)]
d_operand = operand_batching_dims[i_batching]
및d_start = start_indices_batching_dims[i_batching]
입니다.- 그 외에는
full_batching_index[d_operand] = 0
입니다.
offset_index = result_index[offset_dims...]
.full_offset_index = [oi0, ..., 0, ..., oiN]
,oi
은(는) 개인입니다. 요소가offset_index
의 색인에 삽입되고0
가collapsed_slice_dims
,operand_batching_dims
operand_index = full_start_index + full_batching_index + full_offset_index
indices_are_sorted
가 true
이면 구현은 다음과 같이 가정할 수 있습니다.
start_indices
는 start_index_map
를 기준으로 정렬됩니다. 그렇지 않으면
정의되지 않은 경우입니다. 더 공식적으로 indices(result)
의 모든 i1 < i2
에 대해
full_start_index(i1) <= full_start_index(i2)
입니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
텐서 또는 텐서당 양자화 텐서 | (C1), (C8), (C11), (C17), (C19-C21), (C23) |
(I2) | start_indices |
정수 유형의 텐서 | (C2-C3), (C14), (C17), (C22) |
(I3) | offset_dims |
si64 유형의 1차원 텐서 상수 |
(C1), (C4-C5), (C22) |
(I4) | collapsed_slice_dims |
si64 유형의 1차원 텐서 상수 |
(C1), (C6-C9), (C22) |
(I5) | operand_batching_dims |
si64 유형의 1차원 텐서 상수 |
(C1), (C6), (C10-C12), (C16-C18), (C22) |
(I6) | start_indices_batching_dims |
si64 유형의 1차원 텐서 상수 |
(C13~C17) |
(I7) | start_index_map |
si64 유형의 1차원 텐서 상수 |
(C3), (C18~C19) |
(I8) | index_vector_dim |
si64 유형의 상수 |
(C2-C3), (C15), (C22) |
(I9) | slice_sizes |
si64 유형의 1차원 텐서 상수 |
(C9), (C12), (C20-C22) |
(I10) | indices_are_sorted |
i1 유형의 상수 |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서 또는 텐서당 양자화 텐서 | (C5), (C22~C23) |
제약조건
- (C1)
rank(operand) = size(offset_dims) + size(collapsed_slice_dims) + size(operand_batching_dims)
. - (C2)
0 <= index_vector_dim <= rank(start_indices)
. - (C3)
size(start_index_map) = index_vector_dim < rank(start_indices) ? dim(start_indices, index_vector_dim) : 1
. - (C4)
is_unique(offset_dims) and is_sorted(offset_dims)
. - (C5)
0 <= offset_dims < rank(result)
. - (C6)
is_unique(concatenate(collapsed_slice_dims, operand_batching_dims))
- (C7)
is_sorted(collapsed_slice_dims)
. - (C8)
0 <= collapsed_slice_dims < rank(operand)
. - (C9)
slice_sizes[collapsed_slice_dims...] <= 1
. - (C10)
is_sorted(operand_batching_dims)
입니다. - (C11)
0 <= operand_batching_dims < rank(operand)
입니다. - (C12)
slice_sizes[operand_batching_dims...] <= 1
. - (C13)
is_unique(start_indices_batching_dims)
입니다. - (C14)
0 <= start_indices_batching_dims < rank(start_indices)
입니다. - (C15)
index_vector_dim not in start_indices_batching_dims
입니다. - (C16)
size(operand_batching_dims) == size(start_indices_batching_dims)
입니다. - (C17)
dim(operand, operand_batching_dims...) = dim(start_indices, start_indices_batching_dims...)
). - (C18)
is_unique(concatenate(start_index_map, operand_batching_dims))
입니다. - (C19)
0 <= start_index_map < rank(operand)
). - (C20)
size(slice_sizes) = rank(operand)
입니다. - (C21)
0 <= slice_sizes <= shape(operand)
입니다. - (C22)
shape(result) = combine(batch_dim_sizes, offset_dim_sizes)
, 각 항목의 의미는 다음과 같습니다. <ph type="x-smartling-placeholder">- </ph>
batch_dim_sizes = shape(start_indices)
(다음 크기:index_vector_dim
에 해당하는start_indices
은(는) 포함되지 않습니다.offset_dim_sizes = slice_sizes
(다음의 크기:collapsed_slice_dims
및 다음에 해당하는slice_sizes
operand_batching_dims
는 포함되지 않습니다.combine
는batch_dims
에 해당하는 축에batch_dim_sizes
를 배치합니다.offset_dims
에 해당하는 축에서offset_dim_sizes
입니다.
- (C23)
element_type(operand) = element_type(result)
입니다.
예
// %operand: [
// [
// [[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]]
// ]
// ]
// %start_indices: [
// [
// [[0, 0], [1, 0], [2, 1]],
// [[0, 1], [1, 1], [0, 9]]
// ],
// [
// [[0, 0], [2, 1], [2, 2]],
// [[1, 2], [0, 1], [1, 0]]
// ]
// ]
%result = "stablehlo.gather"(%operand, %start_indices) {
dimension_numbers = #stablehlo.gather<
offset_dims = [3, 4],
collapsed_slice_dims = [1],
operand_batching_dims = [0],
start_indices_batching_dims = [1],
start_index_map = [2, 1],
index_vector_dim = 3>,
slice_sizes = array<i64: 1, 1, 2, 2>,
indices_are_sorted = false
} : (tensor<2x3x4x2xi32>, tensor<2x2x3x2xi64>) -> tensor<2x2x3x2x2xi32>
// %result: [
// [
// [
// [[1, 2], [3, 4]],
// [[3, 4], [5, 6]],
// [[13, 14], [15, 16]]
// ],
// [
// [[33, 34], [35, 36]],
// [[35, 36], [37, 38]],
// [[41, 42], [43, 44]]
// ]
// ],
// [
// [
// [[1, 2], [3, 4]],
// [[13, 14], [15, 16]],
// [[21, 22], [23, 24]]
// ],
// [
// [[43, 44], [45, 46]],
// [[33, 34], [35, 36]],
// [[27, 28], [29, 30]]
// ]
// ]
// ]
get_dimension_size
시맨틱
operand
의 지정된 dimension
크기를 생성합니다. 더 공식적으로
result = dim(operand, dimension)
시맨틱은
구성요소입니다. 요소 유형은 무엇이든 될 수 있습니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
양자화 텐서 | (C1) |
(I2) | dimension |
si64 유형의 상수 |
(C1) |
출력
이름 | 유형 |
---|---|
result |
si32 유형의 0차원 텐서 |
제약조건
- (C1)
0 <= dimension < rank(operand)
.
예
// %operand: [[1, 2, 3], [4, 5, 6]]
%result = "stablehlo.get_dimension_size"(%operand) {
dimension = 1 : i64
} : (tensor<2x3xi64>) -> tensor<i32>
// %result: 3
get_tuple_element
<ph type="x-smartling-placeholder"></ph>
시맨틱
operand
튜플의 index
위치에서 요소를 추출하여 다음을 생성합니다.
result
입니다. 더 공식적으로는 result = operand[index]
입니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
tuple | (C1), (C2) |
(I2) | index |
si32 유형의 상수 |
(C1), (C2) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
지원되는 모든 유형 | (C2) |
제약조건
- (C1)
0 <= index < size(operand)
. - (C2)
type(result) = tuple_element_types(operand)[index]
.
예
// %operand: ([1.0, 2.0], (3))
index = 0 : i32
} : (tuple<tensor<2xf32>, tuple<tensor<i32>>>) -> tensor<2xf32>
// %result: [1.0, 2.0]
만약에
시맨틱
true_branch
에서 정확히 하나의 함수를 실행하여 출력을 생성합니다.
pred
값에 따라 false_branch
입니다. 더 공식적으로는 result =
pred ? true_branch() : false_branch()
입니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | pred |
i1 유형의 0차원 텐서 |
|
(I2) | true_branch |
함수 | (C1~C3) |
(I3) | false_branch |
함수 | (C1), (C2) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
results |
텐서, 양자화 텐서 또는 토큰의 가변 수 | (C3) |
제약조건
- (C1)
input_types(true_branch) = input_types(false_branch) = []
. - (C2)
output_types(true_branch) = output_types(false_branch)
. - (C3)
type(results...) = output_types(true_branch)
.
예
// %result_true_branch: 10
// %result_false_branch: 11
// %pred: true
%result = "stablehlo.if"(%pred) ({
"stablehlo.return"(%result_true_branch) : (tensor<i32>) -> ()
}, {
"stablehlo.return"(%result_false_branch) : (tensor<i32>) -> ()
}) : (tensor<i1>) -> tensor<i32>
// %result: 10
상상
시맨틱
operand
에서 요소별로 허수부를 추출하고 다음을 생성합니다.
result
텐서. 더 공식적으로 각 요소 x
에 대해 다음을 실행합니다.
imag(x) = is_complex(x) ? imaginary_part(x) :
constant(0, element_type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 또는 복합 유형의 텐서 | (C1), (C2) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 유형의 텐서 | (C1), (C2) |
제약조건
- (C1)
shape(result) = shape(operand)
. - (C2)
element_type(result)
는 다음과 같이 정의됩니다. <ph type="x-smartling-placeholder">- </ph>
is_complex(operand)
인 경우complex_element_type(element_type(operand))
입니다.- 그 외에는
element_type(operand)
입니다.
예
// %operand: [(1.0, 2.0), (3.0, 4.0)]
%result = "stablehlo.imag"(%operand) : (tensor<2xcomplex<f32>>) -> tensor<2xf32>
// %result: [2.0, 4.0]
인피드
시맨틱
인피드에서 데이터를 읽고 results
를 생성합니다.
infeed_config
의 시맨틱은 구현을 통해 정의됩니다.
results
는 먼저 오는 페이로드 값과
있습니다. 향후 페이로드와 토큰을 두 개로 분할할 계획입니다.
출력을 분리하여 명확성 개선
(#670)
입력
라벨 | 이름 | 유형 |
---|---|---|
(I1) | token |
token |
(I2) | infeed_config |
string 유형의 상수 |
출력
이름 | 유형 | 제약조건 |
---|---|---|
results |
텐서, 양자화 텐서 또는 토큰의 가변 수 | (C1~C3) |
제약조건
- (C1)
0 < size(results)
. - (C2)
is_empty(result[:-1])
또는is_tensor(type(results[:-1]))
. - (C3)
is_token(type(results[-1]))
.
예
// %token: !stablehlo.token
// infeed_queue[0]: [[1, 2], [3, 4]]
// infeed_queue[1]: [[5, 6], [7, 8]]
%results0:2 = "stablehlo.infeed"(%token) {
infeed_config = ""
} : (!stablehlo.token) -> (tensor<2x2xi64>, !stablehlo.token)
// results0#0: [[1, 2], [3, 4]]
%results1:2 = "stablehlo.infeed"(%token) {
infeed_config = ""
} : (!stablehlo.token) -> (tensor<2x2xi64>, !stablehlo.token)
// results1#0: [[5, 6], [7, 8]]
아이오타
시맨틱
0부터 시작하는 오름차순 값으로 output
텐서를 채웁니다.
iota_dimension
측정기준에 따라 표시됩니다. 더 공식적으로
output[output_index] = constant(is_quantized(output) ?
quantize(output_index[iota_dimension], element_type(output)) :
output_index[iota_dimension], element_type(output))
.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | iota_dimension |
si64 |
(C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
output |
정수, 부동 소수점, 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
0 <= iota_dimension < rank(output)
.
예
%output = "stablehlo.iota"() {
iota_dimension = 0 : i64
} : () -> tensor<4x5xi32>
// %output: [
// [0, 0, 0, 0, 0],
// [1, 1, 1, 1, 1],
// [2, 2, 2, 2, 2],
// [3, 3, 3, 3, 3]
// ]
%output = "stablehlo.iota"() {
iota_dimension = 1 : i64
} : () -> tensor<4x5xi32>
// %output: [
// [0, 1, 2, 3, 4],
// [0, 1, 2, 3, 4],
// [0, 1, 2, 3, 4],
// [0, 1, 2, 3, 4]
// ]
is_finite
시맨틱
x
의 값이 유한한지 (즉, 유한하지 않은지) 요소별 검사를 실행합니다.
+Inf, -Inf, 또는 NaN) y
텐서를 생성합니다. isFinite
를 구현합니다.
IEEE-754 사양의 작업을 지원합니다. 양자화 유형의 경우 결과는 다음과 같습니다.
항상 true
입니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | x |
부동 소수점 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
y |
불리언 유형의 텐서 | (C1) |
제약조건
- (C1)
shape(x) = shape(y)
.
예
// Logical values: -Inf, +Inf, NaN, ...
// %x: [0xFFF0000000000000, 0x7FF0000000000000, 0x7FF8000000000000, -10.0, -0.0, 0.0, 10.0]
%y = "stablehlo.is_finite"(%x) : (tensor<7xf64) -> tensor<7xi1>
// %y: [false, false, false, true, true, true, true]
로그
시맨틱
operand
텐서에서 요소별 로그 연산을 실행하고 다음을 생성합니다.
result
텐서. 요소 유형에 따라 다음 작업을 실행합니다.
- 부동 소수점 수: IEEE-754의
log
- 복소수의 경우: 복소수입니다.
- 양자화 유형의 경우:
dequantize_op_quantize(log, operand, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// %operand: [[1.0, 2.0], [3.0, 4.0]]
%result = "stablehlo.log"(%operand) : (tensor<2x2xf64>) -> tensor<2x2xf64>
// %result: [[0.0, 0.69314718055994529], [1.0986122886681098, 1.3862943611198906]]
log_plus_one
시맨틱
operand
텐서에서 요소별 로그와 연산 1개를 수행합니다.
result
텐서를 생성합니다. 요소 유형에 따라 다음 작업을 실행합니다.
- 부동 소수점 수: IEEE-754의
logp1
- 복소수의 경우: 복소수 더하기 1입니다.
- 양자화 유형의 경우:
dequantize_op_quantize(log_plus_one, operand, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// %operand: [0.0, -0.999, 7.0, 6.38905621, 15.0]
%result = "stablehlo.log_plus_one"(%operand) : (tensor<5xf64>) -> tensor<5xf64>
// %result: [0.0, -6.90776825, 2.07944155, 2.0, 2.77258873]
로지스틱
시맨틱
operand
텐서에서 요소별 로지스틱 연산을 실행하고 다음을 생성합니다.
result
텐서. 요소 유형에 따라 다음 작업을 실행합니다.
- 부동 소수점 수: IEEE-754의
division(1, addition(1, exp(-x)))
- 복소수의 경우: 로지스틱입니다.
- 양자화 유형의 경우:
dequantize_op_quantize(logistic, operand, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// %operand: [[0.0, 1.0], [2.0, 3.0]]
%result = "stablehlo.logistic"(%operand) : (tensor<2x2xf64>) -> tensor<2x2xf64>
// %result: [[0.5, 0.73105858], [0.88079708, 0.95257413]]
지도
<ph type="x-smartling-placeholder"></ph>
시맨틱
dimensions
을 따라 지도 함수 computation
를 inputs
에 적용합니다.
result
텐서를 생성합니다.
더 공식적으로는 result[result_index] = computation(inputs...[result_index])
입니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | inputs |
텐서의 가변 수 또는 텐서당 양자화 텐서 | (C1~C4) |
(I2) | dimensions |
si64 유형의 1차원 텐서 상수 |
(C3) |
(I3) | computation |
함수 | (C4) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서 또는 텐서당 양자화 텐서 | (C1), (C4) |
제약조건
- (C1)
shape(inputs...) = shape(result)
. - (C2)
0 < size(inputs) = N
. - (C3)
dimensions = range(rank(inputs[0]))
. - (C4)
computation
의 유형은(tensor<E0>, ..., tensor<EN-1>) -> tensor<E'>
입니다. 여기서Ei = element_type(inputs[i])
및E' = element_type(result)
입니다.
예
// %input0: [[0, 1], [2, 3]]
// %input1: [[4, 5], [6, 7]]
%result = "stablehlo.map"(%input0, %input1) ({
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%0 = stablehlo.multiply %arg0, %arg1 : tensor<i64>
stablehlo.return %0 : tensor<i64>
}) {
dimensions = array<i64: 0, 1>
} : (tensor<2x2xi64>, tensor<2x2xi64>) -> tensor<2x2xi64>
// %result: [[0, 5], [12, 21]]
최대
시맨틱
텐서 lhs
및 rhs
에서 요소별 최대 연산을 실행하고 다음을 생성합니다.
result
텐서. 요소 유형에 따라 다음 작업을 실행합니다.
- 불리언: 논리적 OR.
- 정수의 경우 최대 정수입니다.
- 부동 소수점 수: IEEE-754의
maximum
- 복소수:
(real, imaginary)
쌍의 사전식 최댓값입니다. 복소수에 대한 순서 지정에는 놀라운 의미 체계가 수반됩니다. 앞으로 복소수에 대한 지원을 중단할 계획입니다. (#560) - 양자화 유형의 경우:
<ph type="x-smartling-placeholder">
- </ph>
dequantize_op_quantize(maximum, lhs, rhs, type(result))
.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | lhs |
텐서 또는 텐서당 양자화 텐서 | (C1) |
(I2) | rhs |
텐서 또는 텐서당 양자화 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서 또는 텐서당 양자화 텐서 | (C1) |
제약조건
- (C1)
baseline_type(lhs) = baseline_type(rhs) = baseline_type(result)
.
예
// %lhs: [[1, 2], [7, 8]]
// %rhs: [[5, 6], [3, 4]]
%result = "stablehlo.maximum"(%lhs, %rhs) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>
// %result: [[5, 6], [7, 8]]
최소
시맨틱
텐서 lhs
및 rhs
에서 요소별 최소 연산을 실행하고 다음을 생성합니다.
result
텐서. 요소 유형에 따라 다음 작업을 실행합니다.
- 불리언: 논리적 AND.
- 정수: 정수 최솟값.
- 부동 소수점 수: IEEE-754의
minimum
- 복소수:
(real, imaginary)
쌍의 사전식 최솟값입니다. 복소수에 대한 순서 지정에는 놀라운 의미 체계가 수반됩니다. 앞으로 복소수에 대한 지원을 중단할 계획입니다. (#560) - 양자화 유형의 경우:
<ph type="x-smartling-placeholder">
- </ph>
dequantize_op_quantize(minimum, lhs, rhs, type(result))
.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | lhs |
텐서 또는 텐서당 양자화 텐서 | (C1) |
(I2) | rhs |
텐서 또는 텐서당 양자화 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서 또는 텐서당 양자화 텐서 | (C1) |
제약조건
- (C1)
baseline_type(lhs) = baseline_type(rhs) = baseline_type(result)
.
예
// %lhs: [[1, 2], [7, 8]]
// %rhs: [[5, 6], [3, 4]]
%result = "stablehlo.minimum"(%lhs, %rhs) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>
// %result: [[1, 2], [3, 4]]
곱하기
시맨틱
두 텐서 lhs
및 rhs
의 요소별 곱을 실행하고 다음을 생성합니다.
result
텐서. 요소 유형에 따라 다음 작업을 실행합니다.
- 불리언: 논리적 AND.
- 정수: 정수 곱셈
- 부동 소수점 수: IEEE-754의
multiplication
- 복소수: 복소수 곱셈
- 양자화 유형의 경우:
<ph type="x-smartling-placeholder">
- </ph>
dequantize_op_quantize(multiply, lhs, rhs, type(result))
.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | lhs |
텐서 또는 텐서당 양자화 텐서 | (C1) |
(I2) | rhs |
텐서 또는 텐서당 양자화 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서 또는 텐서당 양자화 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// %lhs: [[1, 2], [3, 4]]
// %rhs: [[5, 6], [7, 8]]
%result = "stablehlo.multiply"(%lhs, %rhs) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>
// %result: [[5, 12], [21, 32]]
negate
시맨틱
operand
텐서의 요소별 부정을 실행하고 result
를 생성합니다.
텐서가 포함됩니다. 요소 유형에 따라 다음 작업을 실행합니다.
- 부호 있는 정수: 정수 부정
- 부호 없는 정수: 부호 있는 정수로 비트캐스트, 정수 부정, 비트캐스트 부호 없는 정수로 되돌립니다.
- 부동 소수점 수: IEEE-754의
negate
- 복소수의 경우: 복소수 부정입니다.
- 양자화 유형의 경우:
dequantize_op_quantize(negate, operand, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
정수, 부동 소수점, 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
정수, 부동 소수점, 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// Negation operation with integer Tensors
// %operand: [0, -2]
%result = "stablehlo.negate"(%operand) : (tensor<2xi32>) -> tensor<2xi32>
// %result: [0, 2]
// Negation operation with with complex tensors
// %operand: (2.5, 0.0)
%result = "stablehlo.negate"(%operand) : (tensor<1xcomplex<f32>>) -> tensor<1xcomplex<f32>>
// %result: [-2.5, -0.0]
않는
시맨틱
operand
텐서의 요소별 NOT을 실행하고 result
텐서를 생성합니다.
요소 유형에 따라 다음 작업을 실행합니다.
- 불리언: 논리 NOT.
- 정수: 비트 NOT.
인수
이름 | 유형 | 제약조건 |
---|---|---|
operand |
부울 또는 정수 유형의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부울 또는 정수 유형의 텐서 | (C1) |
제약조건
- (C1)
type(operand) = type(result)
.
예
// Bitwise operation with with integer tensors
// %operand: [[1, 2], [3, 4]]
%result = "stablehlo.not"(%operand) : (tensor<2x2xi32>) -> tensor<2x2xi32>
// %result: [[-2, -3], [-4, -5]]
// Bitwise operation with with boolean tensors
// %operand: [true, false]
%result = "stablehlo.not"(%operand) : (tensor<2xi1>) -> tensor<2xi1>
// %result: [false, true]
optimization_barrier
시맨틱
operand
를 생성하는 작업이
result
에 종속되고 컴파일러 변환을 방지하는 작업
장벽을 넘어 작업을 이동시키는 것을 방지할 수 있습니다. 그 외에 작업은
ID(예: result = operand
)
인수
이름 | 유형 | 제약조건 |
---|---|---|
operand |
텐서의 가변 수, 텐서당 양자화 텐서 또는 토큰 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서의 가변 수, 텐서당 양자화 텐서 또는 토큰 | (C1) |
제약조건
- (C1)
type(operand...) = type(result...)
.
예
// %operand0: 0.0
// %operand1: 1.0
%result0, %result1 = "stablehlo.optimization_barrier"(%operand0, %operand1) : (tensor<f32>, tensor<f32>) -> (tensor<f32>, tensor<f32>)
// %result0: 0.0
// %result1: 1.0
또는
시맨틱
두 텐서 lhs
및 rhs
의 요소별 OR을 실행하고 result
를 생성합니다.
텐서가 포함됩니다. 요소 유형에 따라 다음 작업을 실행합니다.
- 불리언: 논리적 OR.
- 정수: 비트 OR.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | lhs |
정수 또는 불리언 유형의 텐서 | (C1) |
(I2) | rhs |
정수 또는 불리언 유형의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
정수 또는 불리언 유형의 텐서 | (C1) |
제약조건
- (C1)
type(lhs) = type(rhs) = type(result)
.
예
// Bitwise operation with with integer tensors
// %lhs: [[1, 2], [3, 4]]
// %rhs: [[5, 6], [7, 8]]
%result = "stablehlo.or"(%lhs, %rhs) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>
// %result: [[5, 6], [7, 12]]
// Logical operation with with boolean tensors
// %lhs: [[false, false], [true, true]]
// %rhs: [[false, true], [false, true]]
%result = "stablehlo.or"(%lhs, %rhs) : (tensor<2x2xi1>, tensor<2x2xi1>) -> tensor<2x2xi1>
// %result: [[false, true], [true, true]]
아웃피드
시맨틱
아웃피드에 inputs
를 쓰고 result
토큰을 생성합니다.
outfeed_config
의 시맨틱은 구현을 통해 정의됩니다.
입력
라벨 | 이름 | 유형 |
---|---|---|
(I1) | inputs |
텐서 또는 양자화 텐서의 가변 수 |
(I2) | token |
token |
(I3) | outfeed_config |
string 유형의 상수 |
출력
이름 | 유형 |
---|---|
result |
token |
예
%result = "stablehlo.outfeed"(%input0, %token) {
outfeed_config = ""
} : (tensor<2x2x2xi64>, !stablehlo.token) -> !stablehlo.token
패드
시맨틱
텐서 주변과 요소 사이를 패딩하여 operand
를 확장합니다.
텐서의 반환 값(예: padding_value
)을 반환합니다.
edge_padding_low
및 edge_padding_high
는 추가되는 패딩의 양을 지정합니다.
상위 (지수 0 옆) 및 최고 (가장 높은 지수 옆)에 있는
각 측정기준을 기준으로
지정할 수 있습니다 패딩값은 음수일 수 있습니다. 여기서
음수 패딩의 절댓값은 삭제할 요소 수를 나타냄
추출해야 합니다.
interior_padding
는 둘 사이에 추가되는 패딩의 양을 지정합니다.
각 차원의 요소가 음수가 될 수 없습니다. 내부 패딩이 발생함
음의 가장자리 패딩이
피연산자입니다.
더 공식적으로 result[result_index]
는 다음과 같이 정의됩니다.
- 다음과 같은 경우
operand[operand_index]
result_index = edge_padding_low + operand_index * (interior_padding + 1)
- 그 외에는
padding_value
입니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
텐서 또는 텐서당 양자화 텐서 | (C1), (C2), (C4) |
(I2) | padding_value |
0차원 텐서 또는 텐서당 양자화 텐서 | (C1) |
(I3) | edge_padding_low |
si64 유형의 1차원 텐서 상수 |
(C1), (C4) |
(I4) | edge_padding_high |
si64 유형의 1차원 텐서 상수 |
(C1), (C4) |
(I5) | interior_padding |
si64 유형의 1차원 텐서 상수 |
(C2~C4) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서 또는 텐서당 양자화 텐서 | (C3~C6) |
제약조건
- (C1)
element_type(operand) = element_type(padding_value) = element_type(result)
. - (C2)
size(edge_padding_low) = size(edge_padding_high) = size(interior_padding) = rank(operand)
. - (C3)
0 <= interior_padding
. - (C4)
shape(result) = shape(operand) + edge_padding_low + max(shape(operand) - 1, 0) * interior_padding + edge_padding_high
.
예
// %operand: [
// [1, 2, 3],
// [4, 5, 6]
// ]
// %padding_value: 0
%result = "stablehlo.pad"(%operand, %padding_value) {
edge_padding_low = array<i64: 0, 1>,
edge_padding_high = array<i64: 2, 1>,
interior_padding = array<i64: 1, 2>
} : (tensor<2x3xi32>, tensor<i32>) -> tensor<5x9xi32>
// %result: [
// [0, 1, 0, 0, 2, 0, 0, 3, 0],
// [0, 0, 0, 0, 0, 0, 0, 0, 0],
// [0, 4, 0, 0, 5, 0, 0, 6, 0],
// [0, 0, 0, 0, 0, 0, 0, 0, 0],
// [0, 0, 0, 0, 0, 0, 0, 0, 0]
// ]
partition_id
시맨틱
현재 프로세스의 partition_id
를 생성합니다.
출력
이름 | 유형 |
---|---|
result |
ui32 유형의 0차원 텐서 |
예
%result = "stablehlo.partition_id"() : () -> tensor<ui32>
팝CNT
시맨틱
operand
텐서에 설정된 비트 수의 요소별 카운트 수행
result
텐서를 생성합니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
정수 유형의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
정수 유형의 텐서 | (C1) |
제약조건
- (C1)
type(operand) = type(result)
.
예
// %operand: [0, 1, 2, 127]
%result = "stablehlo.popcnt"(%operand) : (tensor<4xi64>) -> tensor<4xi64>
// %result: [0, 1, 1, 7]
전력
시맨틱
rhs
텐서로 lhs
텐서의 요소별 지수 수행
result
텐서를 생성합니다. 요소 유형에 따라 다음 작업을 실행합니다.
- 정수: 정수 지수
- 부동 소수점 수: IEEE-754의
pow
- 복소수의 경우: 복소수 지수입니다.
- 양자화 유형의 경우:
dequantize_op_quantize(power, lhs, rhs, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | lhs |
정수, 부동 소수점, 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
(I2) | rhs |
정수, 부동 소수점, 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
정수, 부동 소수점, 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// %lhs: [-2.0, -0.0, -36.0, 5.0, 3.0, 10000.0]
// %rhs: [2.0, 2.0, 1.1, 2.0, -1.0, 10.0]
%result = "stablehlo.power"(%lhs, %rhs) : (tensor<6xf64>, tensor<6xf64>) -> tensor<6xf64>
// %result: [4.0, 0.0, -nan, 25.0, 0.333333343, inf]
real
시맨틱
operand
에서 요소별로 실수 부분을 추출하고 result
을 생성합니다.
텐서가 포함됩니다. 더 공식적으로 각 요소 x
에 대해 다음을 실행합니다.
real(x) = is_complex(x) ? real_part(x) : x
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 또는 복합 유형의 텐서 | (C1), (C2) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 유형의 텐서 | (C1), (C2) |
제약조건
- (C1)
shape(result) = shape(operand)
. - (C2)
element_type(result)
는 다음과 같이 정의됩니다. <ph type="x-smartling-placeholder">- </ph>
is_complex(operand)
인 경우complex_element_type(element_type(operand))
입니다.- 그 외에는
element_type(operand)
입니다.
예
// %operand: [(1.0, 2.0), (3.0, 4.0)]
%result = "stablehlo.real"(%operand) : (tensor<2xcomplex<f32>>) -> tensor<2xf32>
// %result: [1.0, 3.0]
recv
시맨틱
channel_id
를 사용하여 채널에서 데이터를 수신하고 results
를 생성합니다.
is_host_transfer
가 true
이면 작업은
호스팅합니다 그렇지 않으면 다른 기기에서 데이터를 전송합니다. 이것이 의미하는 바는
구현 정의입니다. 이 플래그는 다음 위치에 제공된 정보와 중복됩니다.
channel_type
, 앞으로는 둘 중 하나만 유지할 계획입니다.
(#666)
results
는 먼저 오는 페이로드 값과
있습니다. 향후 페이로드와 토큰을 두 개로 분할할 계획입니다.
출력을 분리하여 명확성 개선
(#670)
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | token |
token |
(C4) |
(I2) | channel_id |
si64 유형의 상수 |
|
(I3) | channel_type |
DEVICE_TO_DEVICE 및 HOST_TO_DEVICE 의 열거형 |
(C1) |
(I4) | is_host_transfer |
i1 유형의 상수 |
(C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
results |
텐서, 양자화 텐서 또는 토큰의 가변 수 | (C2~C4) |
제약조건
- (C1)
channel_type
는 다음과 같이 정의됩니다. <ph type="x-smartling-placeholder">- </ph>
is_host_transfer = true
인 경우HOST_TO_DEVICE
,- 그 외에는
DEVICE_TO_DEVICE
입니다.
- (C2)
0 < size(results)
. - (C3)
is_empty(result[:-1])
또는is_tensor(type(results[:-1]))
. - (C4)
is_token(type(results[-1]))
.
예
%results0, %results1 = "stablehlo.recv"(%token) {
channel_handle = #stablehlo.channel_handle<handle = 1, type = 3>,
is_host_transfer = true
} : (!stablehlo.token) -> (tensor<2x2xi64>, !stablehlo.token)
reduce
시맨틱
다음과 같이 축소 함수 body
를 inputs
및 init_values
에 적용합니다.
dimensions
하고 results
텐서를 생성합니다.
축소 순서는 구현으로 정의됩니다. 즉, body
및
init_values
는 작업이 다음을 생성하도록 하기 위해 모노이드를 형성해야 합니다.
모든 구현의 모든 입력에 대해 동일한 결과를 제공합니다. 그러나 이 조건은
많이 감축되지 않고 있습니다. 예: 부동 소수점 덧셈이 사용된
init_values
의 body
와 0은 실제로 모놀이드를 형성하지 않습니다.
부동 소수점 덧셈은 결합 법칙이 아닙니다.
더 공식적으로 results...[j0, ..., jR-1] = reduce(input_slices_converted)
, 각 항목의 의미는 다음과 같습니다.
input_slices = inputs...[j0, ..., :, ..., jR-1]
,:
가 삽입되는 위치dimensions
input_slices_converted = to_destination_type(input_slices..., type(func_inputs(body)[:len(func_inputs(body))//2])...)
.init_values_converted = to_destination_type(init_values..., type(func_inputs(body)[len(func_inputs(body))//2:])...)
.- 일부 바이너리 트리의 경우
reduce(input_slices_converted) = exec(schedule)
schedule
각 항목의 의미는 다음과 같습니다. <ph type="x-smartling-placeholder">- </ph>
exec(node) = body(exec(node.left), exec(node.right))
.exec(leaf) = leaf.value
.
schedule
는 구현에서 정의된 전체 바이너리 트리로, 순서가 순차인 순회는 다음과 같이 구성됩니다. <ph type="x-smartling-placeholder">- </ph>
- 모든
index
에 대한 값input_slices_converted...[index]
개index_space(input_slices_converted)
(오름차순 사전) 총index
페이지입니다. - 구현에서 정의한 양의
구현에서 정의된 위치에
init_values_converted
가 있습니다.
- 모든
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | inputs |
텐서의 가변 수 또는 텐서당 양자화 텐서 | (C1-C4), (C6), (C7) |
(I2) | init_values |
0차원 텐서 또는 텐서당 양자화 텐서의 가변 수 | (C2), (C3) |
(I3) | dimensions |
si64 유형의 1차원 텐서 상수 |
(C4), (C5), (C7) |
(I4) | body |
함수 | (C6) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
results |
텐서의 가변 수 또는 텐서당 양자화 텐서 | (C3), (C7), (C8) |
제약조건
- (C1)
same(shape(inputs...))
. - (C2)
element_type(inputs...) = element_type(init_values...)
. - (C3)
0 < size(inputs) = size(init_values) = size(results) = N
. - (C4)
0 <= dimensions < rank(inputs[0])
. - (C5)
is_unique(dimensions)
. - (C6)
body
의 유형이(tensor<E0>, ..., tensor<EN-1>, tensor<E0>, ...,
입니다.tensor<EN-1>) -> (tensor<E0>, ..., tensor<EN-1>)
여기서is_promotable(element_type(inputs[i]), Ei)
입니다. - (C7)
shape(results...) = shape(inputs...)
(크기가 다음과 같을 때 제외)dimensions
에 해당하는inputs...
크기는 포함되지 않습니다. - (C8)
[0,N)
의 모든i
에 대해element_type(results[i]) = Ei
입니다.
예
// %input = [[0, 1, 2, 3, 4, 5]]
// %init_value = 0
%result = "stablehlo.reduce"(%input, %init_value) ({
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%0 = "stablehlo.add"(%arg0, %arg1) : (tensor<i64>, tensor<i64>) -> tensor<i64>
"stablehlo.return"(%0) : (tensor<i64>) -> ()
}) {
dimensions = array<i64: 1>
} : (tensor<1x6xi64>, tensor<i64>) -> tensor<1xi64>
// %result = [15]
reduce_precision
시맨틱
operand
의 요소별 변환을 다른 부동 소수점 유형으로 변환합니다.
exponent_bits
및 mantissa_bits
를 사용하고 원본으로 돌아갑니다.
부동 소수점 유형을 사용하고 output
텐서를 생성합니다.
공식적인 표현:
- 원래 값의 가수 비트가 업데이트되어 원본을 반올림합니다.
값을
mantissa_bits
로 표현 가능한 가장 가까운 값으로roundToIntegralTiesToEven
시맨틱스. - 그런 다음
mantissa_bits
가 가수 비트 수보다 작으면 가수 비트는mantissa_bits
로 잘립니다. - 그런 다음 중간 결과의 지수 비트가
exponent_bits
에서 제공된 범위를 반환하면 중간 결과가 다음 값으로 오버플로 0으로 바꿀 수 있습니다. 입력합니다. - 양자화 유형의 경우
dequantize_op_quantize( lambda operand: reduce_precision(operand, exponent_bits, mantissa_bits), operand, type(result))
를 실행합니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
(I2) | exponent_bits |
si32 유형의 상수 |
(C2) |
(I3) | mantissa_bits |
si32 유형의 상수 |
(C3) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
output |
부동 소수점 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(output)
. - (C2)
1 <= exponent_bits
. - (C3)
0 <= mantissa_bits
.
예
// Logical values: +Inf, NaN, +Denormal, 0.0, 65519.0, 65520.0
// %operand: [0x7FF0000000000000, 0x7FFFFFFFFFFFFFFF, 0x0000000000000001, 0.0, 65519.0, 65520.0]
%output = "stablehlo.reduce_precision"(%operand) {
exponent_bits = 5 : i32,
mantissa_bits = 10 : i32
} : (tensor<6xf64>) -> tensor<6xf64>
// Logical values: +Inf, NaN, 0.0, 0.0, 65504.0, +Inf
// %output: [0x7FF0000000000000, 0x7FFFFFFFFFFFFFFF, 0.0, 0.0, 65504.0, 0x7FF0000000000000]
reduce_scatter
시맨틱
StableHLO 프로세스 그리드의 각 프로세스 그룹 내에서 축소를 수행하고,
각 프로세스의 operand
텐서 값에 대해 computations
사용
scatter_dimension
에 따른 축소 결과를 여러 부분으로 나누고 분산합니다.
프로세스 간에 분할되는 부분을 처리하여 result
를 생성합니다.
이 작업은 StableHLO 프로세스 그리드를 다음과 같은 process_groups
로 분할합니다.
다음과 같이 정의됩니다.
cross_replica(replica_groups)
channel_id <= 0 and use_global_device_ids = false
인 경우.cross_replica_and_partition(replica_groups)
channel_id > 0 and use_global_device_ids = false
인 경우.flattened_ids(replica_groups)
channel_id > 0 and use_global_device_ids = true
인 경우.
그런 다음 각 process_group
내에서 다음을 실행합니다.
reduced_value = all_reduce(operand, replica_groups, channel_id, use_global_device_ids, computation)
.parts@sender = split(reduced_value@sender, dim(process_groups, 1), scatter_dimension)
.- 모든
sender
의result@receiver = parts@sender[receiver_index]
process_group
, 여기서receiver_index = process_group.index(receiver)
.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
텐서 또는 텐서당 양자화 텐서 | (C1), (C2), (C7), (C8) |
(I2) | scatter_dimension |
si64 유형의 상수 |
(C1), (C2), (C8) |
(I3) | replica_groups |
si64 유형의 2차원 텐서 상수 |
(C3~C5) |
(I4) | channel_id |
si64 유형의 상수 |
(C6) |
(I5) | use_global_device_ids |
i1 유형의 상수 |
(C6) |
(I6) | computation |
함수 | (C7) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서 또는 텐서당 양자화 텐서 | (C8~C9) |
제약조건
- (C1)
dim(operand, scatter_dimension) % dim(process_groups, 1) = 0
. - (C2)
0 <= scatter_dimension < rank(operand)
. - (C3)
is_unique(replica_groups)
. - (C4)
size(replica_groups)
는 다음과 같이 정의됩니다. <ph type="x-smartling-placeholder">- </ph>
cross_replica
가 사용되는 경우num_replicas
cross_replica_and_partition
가 사용되는 경우num_replicas
flattened_ids
가 사용되는 경우num_processes
- (C5)
0 <= replica_groups < size(replica_groups)
. - (C6)
use_global_device_ids = true
인 경우channel_id > 0
- (C7)
computation
에는(tensor<E>, tensor<E>) -> (tensor<E>)
유형이 있습니다. 여기서is_promotable(element_type(operand), E)
입니다. - (C8) 다음을 제외한
shape(result) = shape(operand)
: <ph type="x-smartling-placeholder">- </ph>
dim(result, scatter_dimension) = dim(operand, scatter_dimension) / dim(process_groups, 1)
.
- (C9)
element_type(result) = E
.
예
// num_replicas: 2
// num_partitions: 1
// %operand@(0, 0): [[1, 2, 3, 4],
// [5, 6, 7, 8]]
// %operand@(1, 0): [[9, 10, 11, 12],
// [13, 14, 15, 16]]
%result = "stablehlo.reduce_scatter"(%operand) ({
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%0 = "stablehlo.add"(%arg0, %arg1) : (tensor<i64>, tensor<i64>) -> tensor<i64>
"stablehlo.return"(%0) : (tensor<i64>) -> ()
}) {
scatter_dimension = 1 : i64,
replica_groups = dense<[[0, 1]]> : tensor<1x2xi64>,
channel_handle = #stablehlo.channel_handle<handle = 0, type = 0>
} : (tensor<2x4xi64>) -> tensor<2x2xi64>
//
// %result@(0, 0): [[10, 12],
// [18, 20]]
// %result@(1, 0): [[14, 16],
// [22, 24]]
reduce_window
시맨틱
축소 함수 body
를 inputs
및 init_values
의 기간에 적용
그리고 results
를 생성합니다.
다음 다이어그램은 results...
의 요소가 다음에서 계산되는 방식을 보여줍니다.
구체적인 예를 사용하여 inputs...
더 공식적으로
results...[result_index] = reduce(windows, init_values, axes(inputs...), body)
(축소 참고) 각 항목의 의미는 다음과 같습니다.
padded_inputs = pad(inputs..., init_values..., padding[:, 0], padding[:, 1], base_dilations - 1)
.window_start = result_index * window_strides
.window_end = window_start + (window_dimensions - 1) * window_dilations + 1
.windows = slice(padded_inputs..., window_start, window_end, window_dilations)
.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | inputs |
텐서의 가변 수 또는 텐서당 양자화 텐서 | (C1-C4), (C6), (C8), (C10), (C12), (C13), (C15) |
(I2) | init_values |
0차원 텐서 또는 텐서당 양자화 텐서의 가변 수 | (C1), (C13) |
(I3) | window_dimensions |
si64 유형의 1차원 텐서 상수 |
(C4), (C5), (C15) |
(I4) | window_strides |
si64 유형의 1차원 텐서 상수 |
(C6), (C7), (C15) |
(I5) | base_dilations |
si64 유형의 1차원 텐서 상수 |
(C8), (C9), (C15) |
(I6) | window_dilations |
si64 유형의 1차원 텐서 상수 |
(C10), (C11), (C15) |
(I7) | padding |
si64 유형의 2차원 텐서 상수 |
(C12), (C15) |
(I8) | body |
함수 | (C13) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
results |
텐서의 가변 수 또는 텐서당 양자화 텐서 | (C1), (C14~C16) |
제약조건
- (C1)
0 < size(inputs) = size(init_values) = size(results) = N
. - (C2)
same(shape(inputs...))
. - (C3)
element_type(inputs...) = element_type(init_values...)
. - (C4)
size(window_dimensions) = rank(inputs[0])
. - (C5)
0 < window_dimensions
. - (C6)
size(window_strides) = rank(inputs[0])
. - (C7)
0 < window_strides
. - (C8)
size(base_dilations) = rank(inputs[0])
. - (C9)
0 < base_dilations
. - (C10)
size(window_dilations) = rank(inputs[0])
입니다. - (C11)
0 < window_dilations
입니다. - (C12)
shape(padding) = [rank(inputs[0]), 2]
. - (C13)
body
에는(tensor<E0>, ..., tensor<EN-1>, tensor<E0>, ...,
유형이 있습니다.tensor<EN-1>) -> (tensor<E0>, ..., tensor<EN-1>)
여기서is_promotable(element_type(inputs[i]), Ei)
입니다. - (C14)
same(shape(results...))
입니다. - (C15)
shape(results[0]) = num_windows
, 각 항목의 의미는 다음과 같습니다. <ph type="x-smartling-placeholder">- </ph>
dilated_input_shape = shape(inputs[0]) = 0 ? 0 : (shape(inputs[0]) - 1) * base_dilations + 1
.padded_input_shape = padding[:, 0] + dilated_input_shape + padding[:, 1]
.dilated_window_shape = (window_dimensions - 1) * window_dilations + 1
.is_empty_window = padded_input_shape = 0 || dilated_window_shape > padded_input_shape
.num_windows = is_empty_window ? 0 : floor((padded_input_shape - dilated_window_shape) / window_strides) + 1
.
- (C16)
[0,N)
의 모든i
에 대해element_type(results[i]) = Ei
입니다.
예
// %input = [[1, 2], [3, 4], [5, 6]]
// %init_value = 0
%result = "stablehlo.reduce_window"(%input, %init_value) ({
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%0 = "stablehlo.add"(%arg0, %arg1) : (tensor<i64>, tensor<i64>) -> tensor<i64>
"stablehlo.return"(%0) : (tensor<i64>) -> ()
}) {
window_dimensions = array<i64: 2, 1>,
window_strides = array<i64: 4, 1>,
base_dilations = array<i64: 2, 1>,
window_dilations = array<i64: 3, 1>,
padding = dense<[[2, 1], [0, 0]]> : tensor<2x2xi64>
} : (tensor<3x2xi64>, tensor<i64>) -> tensor<2x2xi64>
// %result = [[0, 0], [3, 4]]
나머지
시맨틱
피제수 lhs
및 제수 rhs
텐서의 요소별 나머지 실행
result
텐서를 생성합니다.
좀 더 공식적으로, 결과의 기호는 피제수에서 가져온 것이고
결과의 절댓값이 항상 제수의 절댓값보다 작습니다.
나머지는 lhs - d * rhs
로 계산되며, 여기서 d
는 다음과 같이 계산됩니다.
- 정수:
stablehlo.divide(lhs, rhs)
. - 부동 소수점 수: 반올림 속성이 있는 IEEE-754의
division(lhs, rhs)
roundTowardZero
- 복소수: 미정 (#997)
- 양자화 유형의 경우:
<ph type="x-smartling-placeholder">
- </ph>
dequantize_op_quantize(remainder, lhs, rhs, type(result))
.
부동 소수점 요소 유형의 경우 이 작업은
d
가 정수 값인 IEEE-754 사양의 remainder
연산
짝수에 연결되며 lhs/rhs
의 정확한 값에 가장 가까운 값입니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | lhs |
정수, 부동 소수점, 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
(I2) | rhs |
정수, 부동 소수점, 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
정수, 부동 소수점, 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// %lhs: [17, -17, 17, -17]
// %rhs: [3, 3, -3, -3]
%result = "stablehlo.remainder"(%lhs, %rhs) : (tensor<4xi64>, tensor<4xi64>) -> tensor<4xi64>
// %result: [2, -2, 2, -2]
replica_id
시맨틱
현재 프로세스의 replica_id
를 생성합니다.
출력
이름 | 유형 |
---|---|
result |
ui32 유형의 0차원 텐서 |
예
%result = "stablehlo.replica_id"() : () -> tensor<ui32>
형태를 변경하다
시맨틱
operand
텐서의 형태를 result
텐서로 변경합니다. 개념적으로
이는 동일한 표준 표현을 유지하지만
도형입니다. 예: tensor<2x3xf32>
에서 tensor<3x2xf32>
또는 tensor<6xf32>
로 변경됩니다.
더 공식적으로 result[result_index] = operand[operand_index]
,
사전식에서 result_index
과 operand_index
의 위치가 같음
index_space(result)
와 index_space(operand)
의 순서입니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
양자화 텐서 | (C1~C3) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
양자화 텐서 | (C1~C3) |
제약조건
- (C1)
element_type(result)
는 다음과 같이 주어집니다. <ph type="x-smartling-placeholder">- </ph>
!is_per_axis_quantized(operand)
인 경우element_type(operand)
입니다.quantization_dimension(operand)
및 다음을 제외하고element_type(operand)
quantization_dimension(result)
는 다를 수 있습니다.
- (C2)
size(operand) = size(result)
. - (C3)
is_per_axis_quantized(operand)
인 경우: <ph type="x-smartling-placeholder">- </ph>
reduce(dims(operand, [0, 1, ..., quantization_dimension(operand) - 1]), init_values=1, dimensions=[0], body=lambda x, y: x * y) = reduce(dims(result, [0, 1, ..., quantization_dimension(result) - 1]), init_values=1, dimensions=[0], body=lambda x, y: x * y)
.dim(operand, quantization_dimension(operand)) = dim(result, quantization_dimension(result))
.reduce(dims(operand, [quantization_dimension(operand) + 1, ..., rank(operand) - 1]), init_values=1, dimensions=[0], body=lambda x, y: x * y) = reduce(dims(result, [quantization_dimension(result) + 1, ..., rank(result) - 1]), init_values=1, dimensions=[0], body=lambda x, y: x * y)
.
예
// %operand: [[1, 2, 3], [4, 5, 6]]
%result = "stablehlo.reshape"(%operand) : (tensor<2x3xi32>) -> tensor<3x2xi32>
// %result: [[1, 2], [3, 4], [5, 6]]
reverse
시맨틱
지정된 dimensions
에 따라 operand
의 요소 순서를 반대로 합니다.
result
텐서를 생성합니다. 더 공식적으로
result[result_index] = operand[operand_index]
각 항목의 의미는 다음과 같습니다.
operand_index[d] = dim(result, d) - result_index[d] - 1
dimensions
에d
인 경우.- 그 외에는
operand_index[d] = result_index[d]
입니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
텐서 또는 텐서당 양자화 텐서 | (C1), (C3) |
(I2) | dimensions |
si64 유형의 1차원 텐서 상수 |
(C2), (C3) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서 또는 텐서당 양자화 텐서 | (C1), (C3) |
제약조건
- (C1)
type(operand) = type(result)
. - (C2)
is_unique(dimensions)
. - (C3)
0 <= dimensions < rank(result)
.
예
// %operand = [[1, 2], [3, 4], [5, 6]]
%result = "stablehlo.reverse"(%operand) {
dimensions = array<i64: 1>
} : (tensor<3x2xi32>) -> tensor<3x2xi32>
// %result: [[2, 1], [4, 3], [6, 5]]
RG
<ph type="x-smartling-placeholder"></ph>
시맨틱
rng_distribution
알고리즘을 사용하여 랜덤 숫자를 생성하고
지정된 셰이프 shape
의 result
텐서.
rng_distribution = UNIFORM
인 경우 랜덤 숫자가 생성됩니다.
이는 간격 [a, b)
에 대한 균일한 분포를 따르는 것입니다. a >= b
인 경우,
정의되지 않은 경우 발생합니다.
rng_distribution = NORMAL
인 경우 랜덤 숫자가 생성됩니다.
평균이 a
이고 표준 편차가 b
인 정규 분포를 따릅니다.
b < 0
인 경우 동작이 정의되지 않습니다.
랜덤 숫자가 생성되는 정확한 방법은 구현을 통해 정의됩니다. 대상 예를 들어 결정론적일 수도 있고 아닐 수도 있으며, 은닉 상태를 처리합니다.
많은 이해 관계자와의 대화에서 이 오퍼는 향후 지원 중단에 대해 알아보고 (#597)
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | a |
정수, 부울, 부동 소수점 유형의 0차원 텐서 | (C1), (C2) |
(I2) | b |
정수, 부울, 부동 소수점 유형의 0차원 텐서 | (C1), (C2) |
(I3) | shape |
si64 유형의 1차원 텐서 상수 |
(C3) |
(I4) | rng_distribution |
UNIFORM 및 NORMAL 의 열거형 |
(C2) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
정수, 부울, 부동 소수점 유형의 텐서 | (C1~C3) |
제약조건
- (C1)
element_type(a) = element_type(b) = element_type(result)
. - (C2)
rng_distribution = NORMAL
이면is_float(a)
입니다. - (C3)
shape(result) = shape
.
예
// %a = 0
// %b = 2
// %shape = [3, 3]
%result = "stablehlo.rng"(%a, %b, %shape) {
rng_distribution = #stablehlo<rng_distribution UNIFORM>
} : (tensor<i32>, tensor<i32>, tensor<2xi64>) -> tensor<3x3xi32>
// %result: [
// [1, 0, 1],
// [1, 1, 1],
// [0, 0, 0]
// ]
rng_bit_generator
시맨틱
임의의 균일 비트와 업데이트된 출력 상태로 채워진 output
를 반환합니다.
의사 난수 생성기 알고리즘 rng_algorithm
을 사용한 output_state
주어진 초기 상태 initial_state
입니다. 출력은
initial_state
의 확정 함수가 제공되지 않을 수도 있습니다.
확정적인 차이를 보입니다
rng_algorithm
는 다음 중 하나입니다.
DEFAULT
: 구현 정의 알고리즘입니다.THREE_FRY
: Threefry 알고리즘의 구현 정의 변형입니다.*PHILOX
: Philox 알고리즘의 구현 정의 변형입니다.*
* 참조: Salmon 외 SC 2011. 평행 랜덤 숫자: 1, 2, 3만큼 쉬움 를 통해 개인정보처리방침을 정의할 수 있습니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | rng_algorithm |
DEFAULT , THREE_FRY , PHILOX 의 열거형 |
(C2) |
(I2) | initial_state |
ui64 유형의 1차원 텐서 |
(C1), (C2) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
output_state |
ui64 유형의 1차원 텐서 |
(C1) |
output |
정수 또는 부동 소수점 유형의 텐서 |
제약조건
- (C1)
type(initial_state) = type(output_state)
. - (C2)
size(initial_state)
는 다음과 같이 정의됩니다. <ph type="x-smartling-placeholder">- </ph>
rng_algorithm = DEFAULT
이면 구현에서 정의됩니다.rng_algorithm = THREE_FRY
인 경우2
입니다.2
또는3
(rng_algorithm = PHILOX
인 경우)
예
// %initial_state: [1, 2]
%output_state, %output = "stablehlo.rng_bit_generator"(%initial_state) {
rng_algorithm = #stablehlo<rng_algorithm THREE_FRY>
} : (tensor<2xui64>) -> (tensor<2xui64>, tensor<2x2xui64>)
// %output_state: [1, 6]
// %output: [
// [9236835810183407956, 16087790271692313299],
// [18212823393184779219, 2658481902456610144]
// ]
round_nearest_afz
시맨틱
가장 가까운 정수로 요소별로 반올림하여 동점을 끊습니다.
operand
텐서에서 0부터 시작하여 result
텐서를 생성합니다. 구현
IEEE-754 사양의 roundToIntegralTiesToAway
연산입니다. 대상
양자화된 유형으로
dequantize_op_quantize(round_nearest_afz, operand, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// %operand = [-2.5, 0.4, 0.5, 0.6, 2.5]
%result = "stablehlo.round_nearest_afz"(%operand) : (tensor<5xf64>) -> tensor<5xf64>
// %result: [-3.0, 0.0, 1.0, 1.0, 3.0]
round_nearest_even
시맨틱
가장 가까운 정수로 요소별로 반올림하여 동점을 끊습니다.
operand
텐서에서 짝수 정수 쪽으로 이동하고 result
을 생성합니다.
텐서가 포함됩니다. IEEE-754에서 roundToIntegralTiesToEven
작업을 구현합니다.
지정할 수도 있습니다 양자화 유형의 경우
dequantize_op_quantize(round_nearest_even, operand, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// %operand = [-2.5, 0.4, 0.5, 0.6, 2.5]
%result = "stablehlo.round_nearest_even"(%operand) : (tensor<5xf64>) -> tensor<5xf64>
// %result: [-2.0, 0.0, 0.0, 1.0, 2.0]
rsqrt
시맨틱
operand
텐서에서 요소별 역수 제곱근 연산을 실행합니다.
result
텐서를 생성합니다. 요소 유형에 따라 다음 작업을 실행합니다.
- 부동 소수점 수: IEEE-754의
rSqrt
- 복소수의 경우: 복소수의 제곱근을 사용합니다.
- 양자화 유형의 경우:
dequantize_op_quantize(rsqrt, operand, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// %operand: [[1.0, 4.0], [9.0, 25.0]]
%result = "stablehlo.rsqrt"(%operand) : (tensor<2x2xf32>) -> tensor<2x2xf32>
// %result: [[1.0, 0.5], [0.33333343, 0.2]]
분산형
시맨틱
다음을 제외하고 inputs
텐서와 동일한 results
텐서를 생성합니다.
scatter_indices
로 지정된 여러 슬라이스가
update_computation
를 사용하여 updates
.
다음 다이어그램은 updates...
의 요소가 다음 위치에 있는 요소에 매핑되는 방식을 보여줍니다.
구체적인 예를 사용하여 results...
이 다이어그램은
updates...
은(는) 어떤 results...
색인을 생성하고 있는지 자세히 설명합니다.
나타냅니다.
더 공식적으로 index_space(updates[0])
의 모든 update_index
에 대해 다음을 실행합니다.
update_scatter_dims = [d for d in axes(updates[0]) and d not in update_window_dims]
.update_scatter_index = update_index[update_scatter_dims...]
.start_index
는 다음과 같이 정의됩니다. <ph type="x-smartling-placeholder">- </ph>
scatter_indices[si0, ..., :, ..., siN]
,si
은(는) 개인입니다. 요소가update_scatter_index
와:
의index_vector_dim
색인,index_vector_dim
<인 경우rank(scatter_indices)
- 그 외에는
[scatter_indices[update_scatter_index]]
입니다.
axes(inputs[0])
의d_input
에 대해 <ph type="x-smartling-placeholder">- </ph>
- 다음과 같은 경우
full_start_index[d_input] = start_index[d_start]
d_input = scatter_dims_to_operand_dims[d_start]
- 그 외에는
full_start_index[d_input] = 0
입니다.
- 다음과 같은 경우
axes(inputs[0])
의d_input
에 대해 <ph type="x-smartling-placeholder">- </ph>
full_batching_index[d_input] = update_scatter_index[d_start - (d_start < index_vector_dim ? 0 : 1)]
d_input = input_batching_dims[i_batching]
및d_start = scatter_indices_batching_dims[i_batching]
입니다.- 그 외에는
full_batching_index[d_input] = 0
입니다.
update_window_index = update_index[update_window_dims...]
.full_window_index = [wi0, ..., 0, ..., wiN]
,wi
은(는) 개인입니다. 요소가update_window_index
의 색인에 삽입되고0
가inserted_window_dims
,input_batching_dims
result_index = full_start_index + full_batching_index + full_window_index
.
이 경우 results = exec(schedule, inputs)
이며, 각 항목의 의미는 다음과 같습니다.
schedule
는 다음과 같은 구현 정의 순열입니다.index_space(updates[0])
exec([update_index, ...], results) = exec([...], updated_results)
각 항목의 의미는 다음과 같습니다. <ph type="x-smartling-placeholder">- </ph>
result_index
가shape(results...)
의 경계 내에 있는 경우updates_converted = to_destination_type( updates...[update_index], type(func_inputs(update_computation) [len(func_inputs(update_computation))//2:])... )
updated_values = update_computation(results...[result_index], updates_converted)
updated_results
은(는)results...[result_index]
이(가) 있는results
의 사본입니다.updated_values...
로 설정합니다.- 그렇지 않은 경우 다음 단계를 따릅니다.
updated_results = results
.
exec([], results) = results
.
indices_are_sorted
가 true
이면 구현은 다음과 같이 가정할 수 있습니다.
scatter_indices
는 scatter_dims_to_operand_dims
,
그렇지 않으면 동작이 정의되지 않습니다. 더 공식적으로, 모든 i1 < i2
indices(result)
, full_start_index(i1)
<= full_start_index(i2)
.
unique_indices
가 true
이면 구현에서는
분산된 result_index
색인이 고유합니다. unique_indices
가 다음에 해당하는 경우
true
이지만 분산된 색인이 고유하지 않은 경우 동작은 다음과 같습니다.
정의되지 않았습니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | inputs |
텐서의 가변 수 또는 텐서당 양자화 텐서 | (C1), (C2), (C4-C6), (C11), (C13), (C18), (C21), (C23-C24) |
(I2) | scatter_indices |
정수 유형의 텐서 | (C4), (C15), (C19), (C22) |
(I3) | updates |
텐서의 가변 수 또는 텐서당 양자화 텐서 | (C3~C6), (C8) |
(I4) | update_window_dims |
si64 유형의 1차원 텐서 상수 |
(C2), (C4), (C7-C8) |
(I5) | inserted_window_dims |
si64 유형의 1차원 텐서 상수 |
(C2), (C4), (C9-C11) |
(I6) | input_batching_dims |
si64 유형의 1차원 텐서 상수 |
(C2), (C4), (C9), (C12-13), (C17-18), (C20) |
(I7) | scatter_indices_batching_dims |
si64 유형의 1차원 텐서 상수 |
(C14~C18) |
(I8) | scatter_dims_to_operand_dims |
si64 유형의 1차원 텐서 상수 |
(C19~C21) |
(I9) | index_vector_dim |
si64 유형의 상수 |
(C4), (C16), (C19), (C22) |
(I10) | indices_are_sorted |
i1 유형의 상수 |
|
(I11) | unique_indices |
i1 유형의 상수 |
|
(I12) | update_computation |
함수 | (C23) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
results |
텐서의 가변 수 또는 텐서당 양자화 텐서 | (C24~C25) |
제약조건
- (C1)
same(shape(inputs...))
. - (C2) `rank(inputs[0]) = size(update_window_dims) + size(inserted_window_dims)
<ph type="x-smartling-placeholder">
- </ph>
- size(input_batching_dims)`.
- (C3)
same(shape(updates...))
. - (C4)
shape(updates[0]) = combine(update_scatter_dim_sizes, update_window_dim_sizes)
, 각 항목의 의미는 다음과 같습니다. <ph type="x-smartling-placeholder">- </ph>
- 다음을 제외하면
update_scatter_dim_sizes = shape(scatter_indices)
scatter_indices
의 크기index_vector_dim
는 포함되지 않습니다. - 다음을 제외하면
update_window_dim_sizes <= shape(inputs[0])
inserted_window_dims
에 해당하는inputs[0]
의 크기 및input_batching_dims
는 포함되지 않습니다. combine
는update_scatter_dim_sizes
을 다음의 축에 배치합니다. 해당하는 축에서update_scatter_dims
및update_window_dim_sizes
update_window_dims
님에게 보냅니다.
- 다음을 제외하면
- (C5)
0 < size(inputs) = size(updates) = N
. - (C6)
element_type(updates...) = element_type(inputs...)
. - (C7)
is_unique(update_window_dims) and is_sorted(update_window_dims)
. - (C8)
0 <= update_window_dims < rank(updates[0])
. - (C9)
is_unique(concatenate(inserted_window_dims, input_batching_dims))
- (C10)
is_sorted(inserted_window_dims)
입니다. - (C11)
0 <= inserted_window_dims < rank(inputs[0])
입니다. - (C12)
is_sorted(input_batching_dims)
. - (C13)
0 <= input_batching_dims < rank(inputs[0]))
입니다. - (C14)
is_unique(scatter_indices_batching_dims)
입니다. - (C15)
0 <= scatter_indices_batching_dims < rank(scatter_indices)
입니다. - (C16)
index_vector_dim not in scatter_indices_batching_dims
입니다. - (C17)
size(input_batching_dims) == size(scatter_indices_batching_dims)
). - (C18)
dim(inputs[0], input_batching_dims...) = dim(scatter_indices, scatter_indices_batching_dims...)
입니다. - (C19)
size(scatter_dims_to_operand_dims) = index_vector_dim < rank(scatter_indices) ? dim(scatter_indices, index_vector_dim) : 1
). - (C20)
is_unique(concatenate(scatter_dims_to_operand_dims, input_batching_dims))
입니다. - (C21)
0 <= scatter_dims_to_operand_dims < rank(inputs[0])
입니다. - (C22)
0 <= index_vector_dim <= rank(scatter_indices)
. - (C23)
update_computation
에는(tensor<E0>, ..., tensor<EN-1>, tensor<E0>, ..., tensor<EN-1>) -> (tensor<E0>, ..., tensor<EN-1>)
유형이 있습니다. 여기서is_promotable(element_type(inputs[i]), Ei)
. - (C24)
shape(inputs...) = shape(results...)
입니다. - (C25)
[0,N)
의 모든i
에 대해element_type(results[i]) = Ei
입니다.
예
// %input: [
// [
// [[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]]
// ]
// ]
// %scatter_indices: [
// [
// [[0, 0], [1, 0], [2, 1]],
// [[0, 1], [1, 1], [0, 9]]
// ],
// [
// [[0, 0], [2, 1], [2, 2]],
// [[1, 2], [0, 1], [1, 0]]
// ]
// ]
// %update: [
// [
// [[1, 1], [1, 1], [1, 1]],
// [[1, 1], [1, 1], [1, 1]]
// ],
// [
// [[1, 1], [1, 1], [1, 1]],
// [[1, 1], [1, 1], [1, 1]]
// ]
// ]
%result = "stablehlo.scatter"(%input, %scatter_indices, %update) ({
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%0 = "stablehlo.add"(%arg0, %arg1) : (tensor<i64>, tensor<i64>) -> tensor<i64>
"stablehlo.return"(%0) : (tensor<i64>) -> ()
}) {
scatter_dimension_numbers = #stablehlo.scatter<
update_window_dims = [3, 4],
inserted_window_dims = [1],
input_batching_dims = [0],
scatter_indices_batching_dims = [1],
scatter_dims_to_operand_dims = [2, 1],
index_vector_dim = 3>,
indices_are_sorted = false,
unique_indices = false
} : (tensor<2x3x4x2xi64>, tensor<2x2x3x2xi64>, tensor<2x2x3x2x2xi64>) -> tensor<2x3x4x2xi64>
// %result: [
// [
// [[3, 4], [6, 7], [6, 7], [7, 8]],
// [[9, 10],[11, 12], [15, 16], [17, 18]],
// [[17, 18], [19, 20], [22, 23], [24, 25]]
// ],
// [
// [[25, 26], [28, 29], [30, 31], [31, 32]],
// [[35, 36], [38, 39], [38, 39], [39, 40]],
// [[41, 42], [44, 45], [46, 47], [47, 48]]
// ]
// ]
select
시맨틱
각 요소가 on_true
또는result
pred
의 상응하는 요소 값에 기반한 on_false
텐서.
더 공식적으로는 result[result_index] = pred_element ? on_true[result_index] :
on_false[result_index]
이며, 여기서 pred_element = rank(pred) = 0 ? pred[] :
pred[result_index]
입니다. 양자화 유형의 경우
dequantize_select_quantize(pred, on_true, on_false, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | pred |
i1 유형의 텐서 |
(C1) |
(I2) | on_true |
텐서 또는 텐서당 양자화 텐서 | (C1~C2) |
(I3) | on_false |
텐서 또는 텐서당 양자화 텐서 | (C2) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서 또는 텐서당 양자화 텐서 | (C2) |
제약조건
- (C1)
rank(pred) = 0 or shape(pred) = shape(on_true)
. - (C2)
baseline_type(on_true) = baseline_type(on_false) = baseline_type(result)
.
예
// %pred: [[false, true], [true, false]]
// %on_true: [[1, 2], [3, 4]]
// %on_false: [[5, 6], [7, 8]]
%result = "stablehlo.select"(%pred, %on_true, %on_false) : (tensor<2x2xi1>, tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>
// %result: [[5, 2], [3, 8]]
select_and_scatter
시맨틱
다음에 따라 scatter
를 사용하여 source
텐서의 값을 분산합니다.
select
를 사용하여 input
텐서의 reduce_window
결과
result
텐서.
다음 다이어그램은 result
의 요소가 다음에서 계산되는 방식을 보여줍니다.
구체적인 예를 사용하여 operand
및 source
를 실행합니다.
공식적인 표현:
selected_values = reduce_window_without_init(...)
를 다음 입력으로 바꿉니다.inputs = [operand].
- 있는 그대로 사용되는
window_dimensions
,window_strides
,padding
입니다. base_dilations = windows_dilations = 1
.body
는 다음과 같이 정의됩니다.
def body(arg0: tensor<E>, arg1: tensor<E>) -> tensor<E>: return select(arg0, arg1) ? arg0 : arg1;
여기서
E = element_type(operand)
,reduce_window_without_init
는reduce_window
와 동일하나, 기본schedule
reduce
(reduce 참고)는 init 값을 포함하지 않습니다. 현재는 해당 창에 값이 없으면 어떻게 되는지 지정하지 않음 (#731)result[result_index] = reduce([source_values], [init_value], [0], scatter)
각 항목의 의미는 다음과 같습니다.source_values = [source[source_index] for source_index in source_indices]
.- 다음과 같은 경우
selected_index(source_index) = operand_index
selected_values[source_index]
에operand
요소가 있음 최저가operand_index
. source_indices = [source_index for source_index in indices(source) if selected_index(source_index) = result_index]
.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
텐서 또는 텐서당 양자화 텐서 | (C1~C4), (C6), (C8~C11) |
(I2) | source |
텐서 또는 텐서당 양자화 텐서 | (C1), (C2) |
(I3) | init_value |
0차원 텐서 또는 텐서당 양자화 텐서 | (C3) |
(I4) | window_dimensions |
si64 유형의 1차원 텐서 상수 |
(C2), (C4), (C5) |
(I5) | window_strides |
si64 유형의 1차원 텐서 상수 |
(C2), (C6), (C7) |
(I6) | padding |
si64 유형의 2차원 텐서 상수 |
(C2), (C8) |
(I7) | select |
함수 | (C9) |
(I8) | scatter |
함수 | (C10) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서 또는 텐서당 양자화 텐서 | (C11~C12) |
제약조건
- (C1)
element_type(operand) = element_type(source)
. - (C2)
shape(source) = num_windows
, 각 항목의 의미는 다음과 같습니다. <ph type="x-smartling-placeholder">- </ph>
padded_operand_shape = padding[:, 0] + shape(operand) + padding[:, 1]
.is_empty_window = padded_operand_shape = 0 || window_dimensions > padded_operand_shape
.num_windows = is_empty_window ? 0 : floor((padded_operand_shape - window_dimensions) / window_strides) + 1
.
- (C3)
element_type(init_value) = element_type(operand)
. - (C4)
size(window_dimensions) = rank(operand)
. - (C5)
0 < window_dimensions
. - (C6)
size(window_strides) = rank(operand)
. - (C7)
0 < window_strides
. - (C8)
shape(padding) = [rank(operand), 2]
. - (C9)
select
에는(tensor<E>, tensor<E>) -> tensor<i1>
유형이 있습니다. 여기서E = element_type(operand)
입니다. - (C10)
scatter
에는(tensor<E>, tensor<E>) -> tensor<E>
유형이 있습니다. 여기서is_promotable(element_type(operand), E)
입니다. - (C11)
shape(operand) = shape(result)
입니다. - (C12)
element_type(result) = E
.
예
// %operand: [[1, 5], [2, 5], [3, 6], [4, 4]]
// %source: [[5, 6], [7, 8]]
// %init_value: 0
%result = "stablehlo.select_and_scatter"(%operand, %source, %init_value) ({
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%0 = "stablehlo.compare"(%arg0, %arg1) {
comparison_direction = #stablehlo<comparison_direction GE>
} : (tensor<i64>, tensor<i64>) -> tensor<i1>
"stablehlo.return"(%0) : (tensor<i1>) -> ()
}, {
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%0 = "stablehlo.add"(%arg0, %arg1) : (tensor<i64>, tensor<i64>) -> tensor<i64>
"stablehlo.return"(%0) : (tensor<i64>) -> ()
}) {
window_dimensions = array<i64: 3, 1>,
window_strides = array<i64: 2, 1>,
padding = dense<[[0, 1], [0, 0]]> : tensor<2x2xi64>
} : (tensor<4x2xi64>, tensor<2x2xi64>, tensor<i64>) -> tensor<4x2xi64>
// %result: [[0, 0], [0, 0], [5, 14], [7, 0]]
보내기
시맨틱
inputs
를 channel_id
채널로 전송하고 result
토큰을 생성합니다.
is_host_transfer
가 true
이면 작업은
호스팅합니다 그렇지 않으면 데이터가 다른 기기로 전송됩니다. 이것이 의미하는 바는
구현 정의입니다. 이 플래그는 다음 위치에 제공된 정보와 중복됩니다.
channel_type
, 앞으로는 둘 중 하나만 유지할 계획입니다.
(#666)
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | inputs |
텐서 또는 양자화 텐서의 가변 수 | |
(I2) | token |
token |
|
(I3) | channel_id |
si64 유형의 상수 |
|
(I4) | channel_type |
DEVICE_TO_DEVICE 및 DEVICE_TO_HOST 의 열거형 |
(C1) |
(I5) | is_host_transfer |
i1 유형의 상수 |
(C1) |
출력
이름 | 유형 |
---|---|
result |
token |
제약조건
- (C1)
channel_type
는 다음과 같이 정의됩니다. <ph type="x-smartling-placeholder">- </ph>
is_host_transfer = true
인 경우DEVICE_TO_HOST
,- 그 외에는
DEVICE_TO_DEVICE
입니다.
예
%result = "stablehlo.send"(%operand, %token) {
channel_handle = #stablehlo.channel_handle<handle = 1, type = 2>,
is_host_transfer = true
} : (tensor<2x2xi64>, !stablehlo.token) -> !stablehlo.token
shift_left
시맨틱
lhs
텐서에서 요소별 왼쪽 시프트 작업을 rhs
숫자만큼 실행합니다.
result
텐서를 생성합니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | lhs |
정수 유형의 텐서 | (C1) |
(I2) | rhs |
정수 유형의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
정수 유형의 텐서 | (C1) |
제약조건
- (C1)
type(lhs) = type(rhs) = type(result)
.
예
// %lhs: [-1, 0, 1]
// %rhs: [1, 2, 3]
%result = "stablehlo.shift_left"(%lhs, %rhs): (tensor<3xi64>, tensor<3xi64>) -> tensor<3xi64>
// %result: [-2, 0, 8]
shift_right_arithmetic
시맨틱
lhs
텐서에서 요소별 라이트 시프트 연산을 다음과 같이 실행합니다.
비트 번호가 rhs
이고 result
텐서가 생성됩니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | lhs |
정수 유형의 텐서 | (C1) |
(I2) | rhs |
정수 유형의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
정수 유형의 텐서 | (C1) |
제약조건
- (C1)
type(lhs) = type(rhs) = type(result)
.
예
// %lhs: [-1, 0, 8]
// %rhs: [1, 2, 3]
%result = "stablehlo.shift_right_arithmetic"(%lhs, %rhs): (tensor<3xi64>, tensor<3xi64>) -> tensor<3xi64>
// %result: [-1, 0, 1]
shift_right_logical
시맨틱
rhs
로 lhs
텐서에서 요소별 논리 오른쪽 시프트 작업을 실행합니다.
숫자를 생성하고 result
텐서를 생성합니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | lhs |
정수 유형의 텐서 | (C1) |
(I2) | rhs |
정수 유형의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
정수 유형의 텐서 | (C1) |
제약조건
- (C1)
type(lhs) = type(rhs) = type(result)
.
예
// %lhs: [-1, 0, 8]
// %rhs: [1, 2, 3]
%result = "stablehlo.shift_right_logical"(%lhs, %rhs): (tensor<3xi64>, tensor<3xi64>) -> tensor<3xi64>
// %result: [9223372036854775807, 0, 1]
서명
시맨틱
요소별로 operand
부호를 반환하고 result
텐서를 생성합니다.
좀 더 공식적으로는 각 요소 x
에 대해 시맨틱을
Python 구문은 다음과 같습니다.
def sign(x):
if is_integer(x):
if compare(x, 0, LT, SIGNED): return -1
if compare(x, 0, EQ, SIGNED): return 0
return 1
elif is_float(x):
if is_nan(x): return NaN
if compare(x, -0.0, EQ, FLOAT): return -0.0
if compare(x, +0.0, EQ, FLOAT): return +0.0
if compare(x, 0.0, LT, FLOAT): return -1.0
return 1.0
elif is_complex(x):
if is_nan(real(x)) or is_nan(imag(x)): return (NaN, NaN)
if compare(x, (0.0, 0.0), EQ, FLOAT): return (0.0, 0.0)
return divide(x, convert(abs(x), type(x)))
양자화 유형의 경우
dequantize_op_quantize(sign, operand, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부호 있는 정수, 부동 소수점, 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부호 있는 정수, 부동 소수점, 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// Logical values: +NaN, -1.0, -0.0, +0.0, 1.0
// operand: [0x7FFFFFFFFFFFFFFF, -1.0, -0.0, 0.0, 1.0]
%result = "stablehlo.sign"(%operand) : (tensor<5xf64>) -> tensor<5xf64>
// Logical values: +NaN, -1.0, -0.0, +0.0, 1.0
// %result: [0x7FFFFFFFFFFFFFFF, -1.0, -0.0, 0.0, 1.0]
사인
시맨틱
operand
텐서에서 요소별 사인 연산을 실행하고 result
를 생성합니다.
텐서가 포함됩니다. 요소 유형에 따라 다음 작업을 실행합니다.
- 부동 소수점 수: IEEE-754의
sin
- 복소수: 복소수 사인
- 양자화 유형의 경우:
dequantize_op_quantize(sine, operand, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// %operand: [
// [0.0, 1.57079632], // [0, pi/2]
// [3.14159265, 4.71238898] // [pi, 3pi/2]
// ]
%result = "stablehlo.sine"(%operand) : (tensor<2x2xf32>) -> tensor<2x2xf32>
// %result: [[0.0, 1.0], [0.0, -1.0]]
slice
시맨틱
정적으로 계산된 시작 색인을 사용하여 operand
에서 슬라이스를 추출합니다.
result
텐서를 생성합니다. start_indices
에는 다음의 시작 색인이 포함됩니다.
각 차원의 슬라이스로 limit_indices
에는 끝 색인이 있습니다.
(제외) 각 차원의 슬라이스에 대해 (제외) strides
에 스트라이드가 포함됨
확인할 수 있습니다
더 공식적으로 result[result_index] = operand[operand_index]
,
operand_index = start_indices + result_index * strides
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
텐서 또는 텐서당 양자화 텐서 | (C1~C3), (C5) |
(I2) | start_indices |
si64 유형의 1차원 텐서 상수 |
(C2), (C3), (C5) |
(I3) | limit_indices |
si64 유형의 1차원 텐서 상수 |
(C2), (C3), (C5) |
(I4) | strides |
si64 유형의 1차원 텐서 상수 |
(C2), (C4) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
텐서 또는 텐서당 양자화 텐서 | (C1), (C5) |
제약조건
- (C1)
element_type(operand) = element_type(result)
. - (C2)
size(start_indices) = size(limit_indices) = size(strides) = rank(operand)
. - (C3)
0 <= start_indices <= limit_indices <= shape(operand)
. - (C4)
0 < strides
. - (C5)
shape(result) = ceil((limit_indices - start_indices) / strides)
.
예
// %operand: [
// [0, 0, 0, 0],
// [0, 0, 1, 1],
// [0, 0, 1, 1]
// ]
%result = "stablehlo.slice"(%operand) {
start_indices = array<i64: 1, 2>,
limit_indices = array<i64: 3, 4>,
strides = array<i64: 1, 1>
} : (tensor<3x4xi64>) -> tensor<2x2xi64>
// % result: [
// [1, 1],
// [1, 1]
// ]
정렬
시맨틱
inputs
의 1차원 슬라이스를 dimension
차원을 따라 함께 정렬합니다.
comparator
에 따라 results
를 생성합니다.
다른 작업의 유사한 입력과 달리 dimension
는 음수 값을 허용합니다.
시맨틱스로 변환합니다 향후 허용되지 않을 수 있습니다.
일관성을 위해
(#1377)
is_stable
이 true이면 정렬이 안정적입니다. 즉,
비교 연산자에 의해 동일한 것으로 간주된 요소는 보존됩니다. 케이스
입력이 하나인 경우 e1
와 e2
두 요소는 다음과 같이 간주됩니다.
다음과 같은 경우에만 비교 연산자와 같음
comparator(e1, e2) = comparator(e2, e1) = false
입니다. 아래 형식 참고
일반화되는 방식을 살펴보겠습니다.
더 공식적으로 index_space(results[0])
의 모든 result_index
에 대해 다음을 실행합니다.
adjusted_dimension = dimension >= 0 ? dimension : rank(inputs[0]) + dimension
.result_slice = [ri0, ..., :, ..., riR-1]
,riN
은(는) 개인입니다. 요소가result_index
에 있고:
가adjusted_dimension
에 삽입됩니다.inputs_together = (inputs[0]..., ..., inputs[N-1]...)
.results_together[result_slice] = sort(inputs_together[result_slice], comparator_together)
.- 여기서
sort
는 1차원 슬라이스를 내림차순이 아닌 순서로 정렬합니다. 왼쪽 인수가 다음과 같은 경우comparator_together
는true
를 반환합니다. 더 작은 값을 가질 수 있습니다. def comparator_together(lhs_together, rhs_together): args = [] for (lhs_el, rhs_el) in zip(lhs_together, rhs_together): args.append(lhs_el) args.append(rhs_el) return comparator(*args)
(results[0]..., ..., results[N-1]...) = results_together
.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | inputs |
텐서의 가변 수 또는 텐서당 양자화 텐서 | (C1~C5) |
(I2) | dimension |
si64 유형의 상수 |
(C4) |
(I3) | is_stable |
i1 유형의 상수 |
|
(I4) | comparator |
함수 | (C5) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
results |
텐서의 가변 수 또는 텐서당 양자화 텐서 | (C2), (C3) |
제약조건
- (C1)
0 < size(inputs)
. - (C2)
type(inputs...) = type(results...)
. - (C3)
same(shape(inputs...) + shape(results...))
. - (C4)
-R <= dimension < R
, 여기서R = rank(inputs[0])
. - (C5)
comparator
에 유형이 있음(tensor<E1>, tensor<E1>, ..., tensor<EN-1>, tensor<EN-1>) -> tensor<i1>
, 여기서Ei = element_type(inputs[i])
.
예
// %input0 = [[1, 2, 3], [3, 2, 1]]
// %input1 = [[3, 2, 1], [1, 2, 3]]
%result0, %result1 = "stablehlo.sort"(%input0, %input1) ({
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>, %arg2: tensor<i64>, %arg3: tensor<i64>):
%predicate = "stablehlo.compare"(%arg0, %arg1) {
comparison_direction = #stablehlo<comparison_direction GT>
} : (tensor<i64>, tensor<i64>) -> tensor<i1>
"stablehlo.return"(%predicate) : (tensor<i1>) -> ()
}) {
dimension = 0 : i64,
is_stable = true
} : (tensor<2x3xi64>, tensor<2x3xi64>) -> (tensor<2x3xi64>, tensor<2x3xi64>)
// %result0 = [[3, 2, 3], [1, 2, 1]]
// %result1 = [[1, 2, 1], [3, 2, 3]]
sqrt
시맨틱
operand
텐서에서 요소별 제곱근 연산을 실행하고 다음을 생성합니다.
result
텐서. 요소 유형에 따라 다음 작업을 실행합니다.
- 부동 소수점 수: IEEE-754의
squareRoot
- 복소수의 경우: 복소수 제곱근입니다.
- 양자화 유형의 경우:
dequantize_op_quantize(sqrt, operand, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// %operand: [[0.0, 1.0], [4.0, 9.0]]
%result = "stablehlo.sqrt"(%operand) : (tensor<2x2xf32>) -> tensor<2x2xf32>
// %result: [[0.0, 1.0], [2.0, 3.0]]
subtract
시맨틱
두 텐서 lhs
및 rhs
의 요소별 뺄셈을 수행하고 다음을 생성합니다.
result
텐서. 요소 유형에 따라 다음 작업을 실행합니다.
- 정수의 경우: 정수 뺄셈.
- 부동 소수점 수: IEEE-754의
subtraction
- 복소수의 경우: 복소수 뺄셈.
- 양자화 유형의 경우:
<ph type="x-smartling-placeholder">
- </ph>
dequantize_op_quantize(subtract, lhs, rhs, type(result))
.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | lhs |
정수, 부동 소수점, 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
(I2) | rhs |
정수, 부동 소수점, 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
정수, 부동 소수점, 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(lhs) = baseline_type(rhs) = baseline_type(result)
.
예
// %lhs: [[6, 8], [10, 12]]
// %rhs: [[5, 6], [7, 8]]
%result = "stablehlo.subtract"(%lhs, %rhs) : (tensor<2x2xf32>, tensor<2x2xf32>) -> (tensor<2x2xf32>)
// %result: [[1, 2], [3, 4]]
tan
시맨틱
operand
텐서에서 요소별 탄젠트 연산을 실행하고 다음을 생성합니다.
result
텐서. 요소 유형에 따라 다음 작업을 실행합니다.
- 부동 소수점 수: IEEE-754의
tan
- 복소수의 경우: 복소 탄젠트입니다.
- 양자화 유형의 경우:
dequantize_op_quantize(tan, operand, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// %operand: [
// [0.0, 1.57079632], // [0, pi/2]
// [3.14159265, 4.71238898] // [pi, 3pi/2]
// ]
%result = "stablehlo.tan"(%operand) : (tensor<2x2xf64>) -> tensor<2x2xf64>
// %result: [
// [0.0, 1.63312e+16],
// [0.0, 5.44375e+15]
// ]
탄
시맨틱
operand
텐서에서 요소별 쌍곡선 탄젠트 연산 실행
result
텐서를 생성합니다. 요소 유형에 따라 다음 작업을 실행합니다.
- 부동 소수점 수: IEEE-754의
tanh
- 복소수: 복소 쌍곡선 탄젠트.
- 양자화 유형의 경우:
<ph type="x-smartling-placeholder">
- </ph>
dequantize_op_quantize(tanh, operand, type(result))
.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_type(operand) = baseline_type(result)
.
예
// %operand: [-1.0, 0.0, 1.0]
%result = "stablehlo.tanh"(%operand) : (tensor<3xf32>) -> tensor<3xf32>
// %result: [-0.76159416, 0.0, 0.76159416]
행열 바꾸기
시맨틱
permutation
를 사용하여 operand
텐서의 크기를 변경하고 다음을 생성합니다.
result
텐서. 더 격식 있는 표현으로 result[result_index] = operand[operand_index]
여기서 result_index[d] = operand_index[permutation[d]]
.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
양자화 텐서 | (C1~C4) |
(I2) | permutation |
si64 유형의 1차원 텐서 상수 |
(C2~C4) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
양자화 텐서 | (C1), (C3~C4) |
제약조건
- (C1)
element_type(result)
는 다음과 같이 주어집니다. <ph type="x-smartling-placeholder">- </ph>
!is_per_axis_quantized(operand)
인 경우element_type(operand)
입니다.quantization_dimension(operand)
및 다음을 제외하고element_type(operand)
quantization_dimension(result)
는 다를 수 있습니다.
- (C2)
permutation
는range(rank(operand))
의 순열입니다. - (C3)
shape(result) = dim(operand, permutation...)
. - (C4)
is_per_axis_quantized(result)
인 경우quantization_dimension(operand) = permutation(quantization_dimension(result))
예
// %operand: [
// [[1,2], [3,4], [5,6]],
// [[7,8], [9,10], [11,12]]
// ]
%result = "stablehlo.transpose"(%operand) {
permutation = array<i64: 2, 1, 0>
} : (tensor<2x3x2xi32>) -> tensor<2x3x2xi32>
// %result: [
// [[1,7], [3,9], [5,11]],
// [[2,8], [4,10], [6,12]]
// ]
triangular_solve
시맨틱
소삼 또는 상삼각을 갖는 일차방정식 연립방정식 배치 풀이 곱합니다.
좀 더 공식적으로 a
및 b
가 주어지면 result[i0, ..., iR-3, :, :]
가 솔루션입니다.
left_side
이(가) 다음 날짜인 경우 op(a[i0, ..., iR-3, :, :]) * x = b[i0, ..., iR-3, :, :]
(으)로
다음 경우 true
또는 x * op(a[i0, ..., iR-3, :, :]) = b[i0, ..., iR-3, :, :]
left_side
은(는) false
입니다. op(a)
이(가) 결정되는 x
변수를 해결합니다.
transpose_a
까지, 이는 다음 중 하나일 수 있습니다.
NO_TRANSPOSE
:a
를 있는 그대로 사용하여 연산을 실행합니다.TRANSPOSE
:a
의 행과 열을 바꿔 작업을 실행합니다.ADJOINT
:a
의 켤레 전치에 대한 연산을 실행합니다.
lower
이 true
인 경우 입력 데이터는 a
의 아래쪽 삼각형에서만 읽습니다.
위쪽 삼각형은 a
입니다. 출력 데이터는 동일한 삼각형에 반환됩니다.
다른 삼각형의 값은 구현으로 정의됩니다.
unit_diagonal
이 true인 경우 구현은 대각선 방향이라고 가정할 수 있습니다.
a
의 요소가 1과 같고, 그렇지 않으면 동작이 정의되지 않습니다.
양자화 유형의 경우
dequantize_op_quantize(lambda x, y: triangular_solve(x, y, left_side, lower,
unit_diagonal, transpose_a), a, b, type(result))
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | a |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1~C3) |
(I2) | b |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1~C4) |
(I3) | left_side |
i1 유형의 상수 |
(C3) |
(I4) | lower |
i1 유형의 상수 |
|
(I5) | unit_diagonal |
i1 유형의 상수 |
|
(I6) | transpose_a |
NO_TRANSPOSE , TRANSPOSE , ADJOINT 의 열거형 |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 또는 복합 유형 또는 텐서당 양자화 텐서의 텐서 | (C1) |
제약조건
- (C1)
baseline_element_type(a) = baseline_element_type(b)
. - (C2)
2 <= rank(a) = rank(b) = R
. - (C3)
shape(a)
과shape(b)
의 관계는 다음과 같이 정의됩니다. <ph type="x-smartling-placeholder">- </ph>
shape(a)[:-3] = shape(b)[:-3]
.dim(a, -2) = dim(a, -1) = dim(b, left_side ? -2 : -1)
.
- (C4)
baseline_type(b) = baseline_type(result)
.
예
// %a = [
// [1.0, 0.0, 0.0],
// [2.0, 4.0, 0.0],
// [3.0, 5.0, 6.0]
// ]
// %b = [
// [2.0, 0.0, 0.0],
// [4.0, 8.0, 0.0],
// [6.0, 10.0, 12.0]
// ]
%result = "stablehlo.triangular_solve"(%a, %b) {
left_side = true,
lower = true,
unit_diagonal = false,
transpose_a = #stablehlo<transpose NO_TRANSPOSE>
} : (tensor<3x3xf32>, tensor<3x3xf32>) -> tensor<3x3xf32>
// %result: [
// [2.0, 0.0, 0.0],
// [0.0, 2.0, 0.0],
// [0.0, 0.0, 2.0]
// ]
tuple
<ph type="x-smartling-placeholder"></ph>
시맨틱
val
값에서 result
튜플을 생성합니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | val |
값의 가변수 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
tuple | (C1) |
제약조건
- (C1)
result
의 유형은tuple<E0, ..., EN-1>
이며 여기서Ei = type(val[i])
입니다.
예
// %val0: [1.0, 2.0]
// %val1: (3)
%result = "stablehlo.tuple"(%val0, %val1) : (tensor<2xf32>, tuple<tensor<i32>>) -> tuple<tensor<2xf32>, tuple<tensor<i32>>>
// %result: ([1.0, 2.0], (3))
uniform_dequantize
시맨틱
양자화 텐서 operand
의 요소별 변환을
정의된 양자화 매개변수에 따른 부동 소수점 텐서 result
operand
유형으로 구분됩니다.
더 공식적으로는 result = dequantize(operand)
입니다.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
양자화 텐서 | (C1), (C2) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부동 소수점 유형의 텐서 | (C1), (C2) |
제약조건
- (C1)
shape(operand) = shape(result)
. - (C2)
element_type(result) = expressed_type(operand)
.
예
// %operand: [10, 10]
%result = "stablehlo.uniform_dequantize"(%operand) : (tensor<2x!quant.uniform<i8:f32:0, {0.1:-30,0.5:-20}>>) -> tensor<2xf32>
// %result: [4.0, 15.0]
uniform_quantize
시맨틱
부동 소수점 텐서 또는 양자화 텐서의 요소별 변환 수행
양자화에 따라 양자화 텐서 result
로의 operand
result
유형으로 정의된 매개변수입니다.
더 공식적으로
is_float(operand)
인 경우: <ph type="x-smartling-placeholder">- </ph>
result = quantize(operand, type(result))
.
is_quantized(operand)
인 경우: <ph type="x-smartling-placeholder">- </ph>
float_result = dequantize(operand)
.result = quantize(float_result, type(result))
.
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
부동 소수점 또는 양자화 유형의 텐서 | (C1), (C2) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
양자화 텐서 | (C1), (C2) |
제약조건
- (C1)
shape(operand) = shape(result)
. - (C2)
expressed_type(result) = is_float(operand) ? element_type(operand) : expressed_type(operand)
.
예
// %operand: [4.0, 15.0]
%result = "stablehlo.uniform_quantize"(%operand) : (tensor<2xf32>) -> tensor<2x!quant.uniform<i8:f32:0, {0.1:-30,0.5:-20}>>
// %result: [10, 10]
// %operand: [10, 10]
%result = "stablehlo.uniform_quantize"(%operand) : (tensor<2x!quant.uniform<i8:f32:0, {0.1:-30,0.5:-20}>>) -> tensor<2x!quant.uniform<i8:f32:0, {0.1:-20,0.2:-30}>>
// %result: [20, 45]
동안
시맨틱
body
함수를 0회 이상 실행하여 출력을 생성합니다.
cond
함수는 true
를 출력합니다. 더 공식적으로 시맨틱스는
사용하여 다음 명령어를 실행합니다.
internal_state = operand
while cond(*internal_state):
internal_state = body(*internal_state)
results = internal_state
무한 루프의 동작은 미정입니다. (#383)
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | operand |
텐서, 양자화 텐서 또는 토큰의 가변 수 | (C1~C3) |
(I2) | cond |
함수 | (C1) |
(I3) | body |
함수 | (C2) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
results |
텐서, 양자화 텐서 또는 토큰의 가변 수 | (C3) |
제약조건
- (C1)
cond
에는(T0, ..., TN-1) -> tensor<i1>
유형이 있습니다. 여기서Ti = type(operand[i])
입니다. - (C2)
body
에는(T0, ..., TN-1) -> (T0, ..., TN-1)
유형이 있습니다. 여기서Ti = type(operand[i])
입니다. - (C3)
type(results...) = type(operand...)
.
예
// %init_i: 1
// %init_sum: 0
// %one: 1
// %ten: 10
%results0, %results1 = "stablehlo.while"(%init_i, %init_sum) ({
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%cond = "stablehlo.compare"(%arg0, %ten) {
comparison_direction = #stablehlo<comparison_direction LT>
} : (tensor<i64>, tensor<i64>) -> tensor<i1>
stablehlo.return %cond : tensor<i1>
}, {
^bb0(%arg0: tensor<i64>, %arg1: tensor<i64>):
%new_sum = stablehlo.add %arg1, %one : tensor<i64>
%new_i = stablehlo.add %arg0, %one : tensor<i64>
stablehlo.return %new_i, %new_sum : tensor<i64>, tensor<i64>
}) : (tensor<i64>, tensor<i64>) -> (tensor<i64>, tensor<i64>)
// %results0: 10
// %results1: 10
XOR
시맨틱
두 텐서 lhs
및 rhs
의 요소별 XOR을 실행하고 result
를 생성합니다.
텐서가 포함됩니다. 요소 유형에 따라 다음 작업을 실행합니다.
- 불리언: 논리 XOR
- 정수: 비트 XOR
입력
라벨 | 이름 | 유형 | 제약조건 |
---|---|---|---|
(I1) | lhs |
부울 또는 정수 유형의 텐서 | (C1) |
(I2) | rhs |
부울 또는 정수 유형의 텐서 | (C1) |
출력
이름 | 유형 | 제약조건 |
---|---|---|
result |
부울 또는 정수 유형의 텐서 | (C1) |
제약조건
- (C1)
type(lhs) = type(rhs) = type(result)
.
예
// Bitwise operation with with integer tensors
// %lhs: [[1, 2], [3, 4]]
// %rhs: [[5, 6], [7, 8]]
%result = "stablehlo.xor"(%lhs, %rhs) : (tensor<2x2xi32>, tensor<2x2xi32>) -> tensor<2x2xi32>
// %result: [[4, 4], [4, 12]]
// Logical operation with with boolean tensors
// %lhs: [[false, false], [true, true]]
// %rhs: [[false, true], [false, true]]
%result = "stablehlo.xor"(%lhs, %rhs) : (tensor<2x2xi1>, tensor<2x2xi1>) -> tensor<2x2xi1>
// %result: [[false, true], [true, false]]
언어 상호 운용성
현재 실제 StableHLO 프로그램에는 StableHLO에 의해 정의되지 않습니다.
모듈, 함수, 호출, 반환
StableHLO는 ModuleOp, FuncOp, CallOp 및 ReturnOp 이 작업은 기존 MLIR 기계와의 상호 운용성을 높이기 위해 수행되었으며, 유용한 패스는 FuncOp, ModuleOp 및 많은 컴파일을 대상으로 작성됩니다. 파이프라인은 이러한 작업이 있을 것으로 예상합니다 완전한 호환성 보장은 적용됩니다 한 번에 이러한 op에 변경사항이 생기면 HLO와 상응하는 것이 호환되지 않는 방식 (즉, 삭제)이 있는 경우, 호환성을 제공합니다
CHLO
CHLO 작업 세트에는 StableHLO로 분해되는 상위 수준의 작업이 포함됩니다. 현재 CHLO에 대한 호환성 보장은 없습니다. 호환성 chlo-legalize-to-stablehlo 패스는 는 직렬화 전에 사용되어야 합니다.
도형 작업
커뮤니티의 일반적인 사용 사례로는 핵심 리소스에서 특정 작업을
동적 StableHLO 프로그램의 MLIR 방언을 사용하여 형태 계산을 수행합니다.
가장 일반적으로는 shape
언어가 포함됩니다.
shape_of
또는 num_elements
, tensor
언어와 같은 작업
dim
또는 from_elements
와 같은 연산 및 내장된 index
유형을 사용합니다.
Dynamism RFC > O2
범위 외로 표시되지만 index
유형에 관한 일부 지원은
포함되어 있습니다. 이러한 항목은 호환성이 보장되지 않습니다.
선택할 수 있습니다 shape-legalize-to-stablehlo
Pass는 이러한 작업을 완전히 지원되는 StableHLO 작업으로 변환하는 데 사용할 수 있습니다.
지원 중단된 작업
여러 StableHLO 작업이 MHLO 지원 중단되었으며 StableHLO에서 지원이 중단될 예정입니다. 이러한 삭제 내용은 StableHLO v1.0 정리 #2283에서 확인할 수 있습니다. 이러한 지원 중단에 관한 추적기 문제는 #2340입니다.
이 작업은 몇 가지 카테고리로 분류됩니다.
- 'HLO에 없음' 이들은 StableHLO 운영 카테고리입니다.
StableHLO Opset이지만 나중에 적합하지 않은 것으로 간주됩니다.
broadcast
,create_token
,cross-replica-sum
,dot
,einsum
unary_einsum
년torch_index_select
(#3). - 사용되지 않는 작업 - 이러한 작업은 어느 시점에 유용했을 수도 있지만
충분히 개발되지 않았거나 이러한 작업을 사용하는 파이프라인이
더 이상 필요하지 않도록 리팩터링되었습니다. 여기에는
map
,tuple
(#598),get_tuple_element
,rng
,complex
비교 #560, 및 컨볼루션window_reversal
(#1181)입니다.
이러한 작업 중 일부는
기존 작업 (broadcast
, create_token
, cross-replica-sum
, dot
,
unary_einsum
) 기존 호환성 기간 이후 삭제됩니다.
6개월). 다른 항목은 아직 삭제를 위해 검토 중입니다 (einsum
,
get_tuple_element
님, map
님, rng
님, torch_index_select
님, tuple
님, complex
님
비교, window_reversal
) 커뮤니티 의견을 기다리는 중입니다.
이러한 작업은 삭제되거나 완전 지원과 함께 사양에 추가됩니다. 종료
이러한 Ops future는 알려져 있으며 6개월의 호환성만 보장됩니다.
실행
순차적 실행
StableHLO 프로그램은 main
함수에 입력 값을 제공하여 실행됩니다.
출력값을 계산하게 됩니다. 함수의 출력값은 다음과 같이 계산됩니다.
상응하는 return
작업에 루팅된 작업의 그래프를 실행합니다.
실행 순서는
즉, 작업이 사용 전에 실행되는지와 같은 데이터 흐름에 영향을 미칠 수 있습니다. StableHLO에서는
부작용 작업은 하나의 토큰을 소비하고 하나의 토큰을 생성하며 (여러 개의 토큰은
after_all
를 통해 하나의 토큰으로 멀티플렉싱되므로 쪽의 실행 순서는
효과도 데이터 흐름과 일치합니다 예를 들어 아래 프로그램에서
가능한 실행 순서는 두 가지입니다. %0
→ %1
→ %2
→ return
및
%1
→ %0
→ %2
→ return
.
func.func @main() -> tensor<f64> {
%0 = stablehlo.constant dense<1.0> : tensor<f64>
%1 = stablehlo.constant dense<2.0> : tensor<f64>
%2 = stablehlo.add %0, %1 : tensor<f64>
return %2 : tensor<f64>
}
더 공식적으로 StableHLO 프로세스는 다음 항목의 조합입니다.
1) StableHLO 프로그램, 2) 작업 상태 (아직 실행되지 않음,
3) 프로세스에서 작업 중인 중간값을 나타냅니다.
프로세스는 main
함수의 입력 값으로 시작하여
작업 상태와 중간값을 업데이트하는 작업의 그래프
출력 값으로 끝납니다. 추가 형식화는 미정
(#484)
동시 실행
StableHLO 프로그램을 2D 프로세스 그리드로 구성하여 병렬로 실행할 수 있음
둘 다 ui32
유형이 있는 num_partitions
의 num_replicas
중 하나입니다.
StableHLO 프로세스 그리드에서 StableHLO의 num_replicas * num_partitions
여러 프로세스가 동시에 실행됩니다 각 프로세스에는 고유한
process_id = (replica_id, partition_id)
, 각 항목의 의미는 다음과 같습니다.
replica_ids = range(num_replicas)
의 replica_id
및
partition_ids = range(num_partitions)
의 partition_id
이며
ui32
를 입력합니다.
프로세스 그리드의 크기는 모든 프로그램(
향후 StableHLO 프로그램의 명시적 일부로 제공할 계획입니다.
#650), 위치
모든 프로세스에 대해 정적으로 알려져 있습니다 각 프로세스에는
replica_id
를 통해 프로세스 그리드 내 위치 액세스
partition_id
작업.
프로세스 그리드 내에서 프로그램은 모두 동일할 수 있습니다('단일 프로그램, 다중 데이터' 모두 다를 수 있습니다("여러 프로그램', 여러 데이터' 스타일) 또는 그 사이의 무언가를 가질 수 있습니다. 앞으로 병렬 StableHLO 프로그램을 정의하는 다른 관용구를 위한 지원 도입 (#619)
프로세스 그리드 내에서 프로세스는 대부분 서로 독립적입니다. 작업 상태, 입력/중간/출력 값이 각각 다릅니다. 대부분의 작업은 프로세스 간에 개별적으로 실행되므로 단, 아래에 설명된 소수의 집단적 운영팀을 제외하고는 예외적으로 허용됩니다.
대부분의 작업이 동일한 작업의 값만 사용된다는 점을 고려했을 때
일반적으로 이러한 값을 이름으로 참조하는 것이 명확합니다.
그러나 집합적 작업의 의미 체계를 설명할 때는 충분하지 않습니다.
name
값을 참조하는 name@process_id
표기법을 일으킵니다.
특정 프로세스 내에서 수행될 수 있습니다. (이 관점에서 정규화되지 않은 name
는
name@(replica_id(), partition_id())
의 약칭으로 표시됨).
프로세스 전반의 실행 순서는 구현을 통해 정의됩니다. 단, 포인트 간 통신 및 집합 운영에 의해 도입된 동기화 변경할 수 있습니다.
지점 간 통신
StableHLO 프로세스는
StableHLO 채널. 채널은 유형의 양수 ID로 표현됩니다.
si64
다양한 작업을 통해 채널에 값을 보내고
채널에서 수신합니다.
추가 형식화. 예: 유입 경로, 채널 ID의 출처, 어떤 종류의 동기화가 동기화 될 수 있는지, 도입 여부는 미정입니다. (#484)
스트리밍 통신
모든 StableHLO 프로세스는 2개의 스트리밍 인터페이스에 액세스할 수 있습니다.
- 읽을 수 있는 인피드입니다.
- 쓰기 가능한 아웃피드입니다.
프로세스 간 통신에 사용되므로 채널과 달리 인피드 및 아웃피드에는 구현이 정의되어 있습니다.
추가 형식화. 예: 스트리밍 통신이 실행에 미치는 영향 어떤 종류의 동기화인지는 미정입니다. (#484)
집단 작전
StableHLO에는 all_gather
, all_reduce
,
all_to_all
, collective_broadcast
, collective_permute
외
reduce_scatter
이러한 모든 작업은 StableHLO 프로세스의 프로세스를 분할합니다.
그리드를 StableHLO 프로세스 그룹으로 변환하고 내부에서 공동 계산을 실행합니다.
각 프로세스 그룹을 다른 프로세스 그룹과 독립적으로
관리할 수 있습니다
각 프로세스 그룹 내에서 집합 운영팀은 동기화 프로세스를 도입하여 있습니다. 추가 형식화. 예: 이 작업이 정확히 언제 이루어지는지에 대해 프로세스가 정확히 어떻게 이 장벽에 도달하는지, 그렇지 않으면 어떻게 되는지는 미정입니다. (#484)
프로세스 그룹이 파티션 간 통신과 관련된 경우, 즉
파티션 ID가 다른 프로세스 그룹의 프로세스를
한 집단의 작전에는 채널이 필요하며, 집단 작전은
si64
유형의 양수 channel_id
복제본 간 통신은 필요하지 않음
있습니다.
집합 작전에서 수행하는 계산은 개별 작업마다 다릅니다. 위의 개별 작업 섹션에 설명되어 있습니다. 그러나 프로세스 그리드가 프로세스 그룹으로 분할되어 이러한 작업 간에 공유됩니다. 이 섹션에서 설명합니다. 더 공식적으로 StableHLO는 네 가지 전략을 살펴보겠습니다
cross_replica
각 프로세스 그룹 내에서 복제본 간 통신만 발생합니다. 이
이 전략은 복제본 ID 및 컴퓨팅 목록인 replica_groups
를 사용합니다.
partition_ids
의 replica_groups
에 대한 데카르트 곱입니다. replica_groups
고유한 요소가 있어야 하며 replica_ids
를 모두 포함해야 합니다. 더 공식적으로
Python 구문:
def cross_replica(replica_groups: List[List[ReplicaId]]) -> List[List[ProcessId]]:
for replica_group in replica_groups:
for partition_id in partition_ids:
process_group = []
for replica_id in replica_group:
process_group.append((replica_id, partition_id))
yield process_group
예를 들어 replica_groups = [[0, 1], [2, 3]]
및 num_partitions = 2
의 경우
cross_replica
에서
[[(0, 0), (1, 0)], [(0, 1), (1, 1)], [(2, 0), (3, 0)], [(2, 1), (3, 1)]]
입니다.
cross_partition
파티션 간 통신만 각 프로세스 그룹 내에서 발생합니다. 이
이 전략은 파티션 ID 목록인 partition_groups
를 사용합니다.
replica_ids
에서 partition_groups
의 카티전 프로덕트를 계산합니다.
partition_groups
는 고유한 요소가 있어야 하며 모든 partition_ids
를 포함해야 합니다.
보다 공식적으로 Python 구문을 사용하는 경우:
def cross_partition(partition_groups: List[List[PartitionId]]) -> List[List[ProcessId]]:
for partition_group in partition_groups:
for replica_id in replica_ids:
process_group = []
for partition_id in partition_group:
process_group.append((replica_id, partition_id))
yield process_group
예를 들어 partition_groups = [[0, 1]]
및 num_replicas = 4
의 경우
cross_partition
에서
[[(0, 0), (0, 1)], [(1, 0), (1, 1)], [(2, 0), (2, 1)], [(3, 0), (3, 1)]]
입니다.
cross_replica_and_partition
복제본 간 통신과 파티션 간 통신이 모두 각 클러스터 내에서 발생할 수 있습니다.
프로세스 그룹입니다 이 전략에서는 replica_groups
- 목록의
복제본 ID - 다음 값을 사용하여 각 replica_group
의 카티전 프로덕트를 계산
partition_ids
입니다. replica_groups
은(는) 고유한 요소가 있어야 하며 모든 요소를 포함해야 합니다.
replica_ids
보다 공식적으로 Python 구문을 사용하는 경우:
def cross_replica_and_partition(replica_groups: List[List[ReplicaId]]) -> List[List[ProcessId]]:
for replica_group in replica_groups:
process_group = []
for partition_id in partition_ids:
for replica_id in replica_group:
process_group.append((replica_id, partition_id))
yield process_group
예를 들어 replica_groups = [[0, 1], [2, 3]]
및 num_partitions = 2
의 경우
cross_replica_and_partition
에서
[[(0, 0), (1, 0), (0, 1), (1, 1)], [(2, 0), (3, 0), (2, 1), (3, 1)]]
입니다.
flattened_ids
이 전략에서는 '평면화된' 목록인 flattened_id_groups
를 사용합니다.
replica_id * num_partitions + partition_id
형식의 프로세스 ID - 그리고
프로세스 ID로 변환합니다. flattened_id_groups
에는 고유 요소가 있어야 합니다.
process_ids
전체를 덮습니다. 보다 공식적으로 Python 구문을 사용하는 경우:
def flattened_ids(flattened_id_groups: List[List[ui32]]) -> List[List[ProcessId]]:
for flattened_id_group in flattened_id_groups:
process_group = []
for flattened_id in flattened_id_group:
replica_id = flattened_id // num_partitions
partition_id = flattened_id % num_partitions
process_group.append((replica_id, partition_id))
yield process_group
예를 들어 flattened_id_groups = [[0, 1, 2, 3], [4, 5, 6, 7]]
의 경우
num_replicas = 4
, num_partitions = 2
, flattened_ids
에서
[[(0, 0), (0, 1), (1, 0), (1, 1)], [(2, 0), (2, 1), (3, 0), (3, 1)]]
입니다.
정확성
현재 StableHLO는 숫자 정확성을 보장하지 않습니다. 향후 변경될 수 있습니다. (#1156)
양자화 작업의 실행 시맨틱스
양자화된 StableHLO 작업의 해석은 설계할 수 있습니다 예를 들어 일부 하드웨어는 양자화 연산을 해석하는 것을 마지막으로 양자화" 전략입니다. 다른 사용자는 전체 정수 산술 계산을 사용합니다. 결과적으로 양자화된 StableHLO 연산은 오직 특정 있습니다. 하이브리드 양자화의 해석 (#1575)는 다음을 기반으로 합니다. 사양에 규정된 대로 it의 의미 체계를 사용할 수 있습니다( 1792).
오류
StableHLO 프로그램은 HLOX 프로그램과 비교하여 개별 오퍼레이션을 적용하여 런타임 전에 많은 종류의 오류를 배제합니다. 그러나 다음과 같은 오류 조건은 여전히 발생할 수 있습니다. 정수 오버플로우, 명시적으로 호출되지 않는 한 이러한 모든 오류는 구현 정의 동작이 발생하지만 이로 인해 향후 (#1157)
부동 소수점 예외
이 규칙에 대한 예외로 StableHLO 프로그램의 부동 소수점 예외는
잘 정의된 것입니다 에 의해 정의된 예외가 발생하는 연산
IEEE-754 표준 (잘못된 연산, 0으로 나누기, 오버플로, 언더플로 또는
잘못된 예외)는 기본 결과를 생성하며 (표준에 정의된 대로)
해당 상태 플래그를 발생시키지 않고 실행을 계속합니다. 다음과 유사:
표준에서 raiseNoFlag
예외를 처리합니다. 비표준 관련 예외
복잡한 산술과 특정한 초월 함수)은
구현 정의입니다.
모양 불일치
StableHLO는 동적 형태 텐서를 지원합니다. 하지만 도형은 런타임이 아니면 동작이 정의되지 않습니다. StableHLO는 명시적으로 런타임에 텐서가 주어진 형태를 지니고 있음을 어설션할 수 있는 작업을 제공합니다. 올바른 코드를 생성하는 것은 제작자의 책임입니다.
예를 들어 아래 프로그램이 유효합니다. 그러나 런타임 시
%arg0
및 %arg1
의 모양은 동일해야 합니다. 그렇지 않으면
정의되지 않은 경우는 다음과 같습니다.
func.func @foo(%arg0: tensor<?xi32>, %arg1: tensor<?xi32>) -> tensor<?xi32> {
%0 = stablehlo.add %arg0, %arg1 : tensor<?xi32>
return %0 : tensor<?xi32>
}
Notation
문법을 설명하기 위해 이 문서에서는 EBNF의 수정된 ISO 버전을 사용합니다.
구문 (ISO/IEC 14977:1996,
위키백과),
다음 두 가지 수정사항이 있습니다. 1) 규칙이 =
가 아닌 ::=
를 사용하여 정의됩니다.
2) 연결은 ,
대신 병치를 사용하여 표현됩니다.
의미 체계를 설명하는 경우('유형', '상수', '작업' 섹션 내) 우리는 Python 구문을 기반으로 하는 공식을 사용하고 있습니다. 를 사용하세요. 잘 작동함 작은 코드 스니펫에 사용할 수 있지만 드물게 더 큰 코드 스니펫이 항상 명시적으로 도입되는 바닐라 Python 구문을 사용합니다.
수식
dot_general
의 예를 기반으로 수식이 작동하는 방식을 살펴보겠습니다.
지정할 수도 있습니다 이 작업의 제약 조건 중 하나는 다음과 같습니다.
dim(lhs, lhs_batching_dimensions...) = dim(rhs, rhs_batching_dimensions...)
이 수식에 사용되는 이름은 1) 전역 함수,
즉, dim
, 2) 상응하는 프로그램 요소의 멤버 정의, 즉
lhs
, lhs_batching_dimensions
, rhs
, rhs_batching_dimensions
입력
'Inputs'에 정의되어 있고 섹션(dot_general
의 섹션)을 참조하세요.
위에서 언급했듯이 이 수식의 구문은 Python 기반이며 일부 간결성 지향 확장 프로그램입니다. 공식을 이해하기 위해 바닐라 Python 구문으로 변환할 수 있습니다.
A) 이 수식에서는 =
을 사용하여 등호를 나타내므로 첫 번째 단계는
Python 구문을 가져오기 위해 다음과 같이 =
를 ==
로 대체합니다.
dim(lhs, lhs_batching_dimensions...) == dim(rhs, rhs_batching_dimensions...)
입니다.
B) 또한 이 수식은 스칼라 표현식을 전환하는 생략 부호 (...
)를 지원합니다.
텐서 표현식으로 변환합니다. 간단히 말해 f(xs...)
는 대략적으로 '각각
xs
텐서에서 스칼라 x
실행, 스칼라 f(x)
계산 후 모두 반환
텐서 결과가 됩니다. 바닐라 Python 구문에서
예시 공식은 다음과 같이 변환됩니다.
[dim(lhs, dim1) for dim1 in lhs_batching_dimensions] ==
[dim(rhs, dim2) for dim2 in rhs_batching_dimensions]
생략 부호 덕분에 대부분의 경우
개별 스칼라입니다 그러나 일부 까다로운 경우에는
하위 수준의 반 비공식적인
start_indices[bi0, ..., :, ..., biN]
수식에서와 같이 문법을 사용할 수 있습니다.
gather
사양에서 가져옴 간결성을 제공하기 위해
이러한 구문을 바닐라 Python으로 변환하기 위한 정확한 형식성을
그럼에도 사례별로 직관적으로 이해하기를 바랍니다.
일부 특정 수식이 불투명해 보이는 경우 알려주시면
개선할 수 있습니다
또한 공식에서는 생략 부호를 사용하여 모든 종류의 목록을 확장합니다. 텐서, 텐서 목록 (예: 텐서 수) 등이 있습니다. 이 역시 정확한 형식성 (예: 목록은 StableHLO 유형 시스템의 일부가 아님) 및 대신 직관적인 이해에 의존해야 합니다.
C) 마지막으로 주목할 만한 표기법 차량은 암시적인 표현을 사용함 있습니다. StableHLO 작업 집합은 암시적 브로드캐스팅을 지원하지 않지만 공식을 사용할 수 있으며, 간결성을 위해 사용됩니다. 간단히 말해서, 스칼라가 텐서가 예상되는 컨텍스트에서 사용되는 경우, 스칼라는 표시됩니다.
dot_general
예시를 계속 사용하기 위한 또 다른 제약조건은 다음과 같습니다.
0 <= lhs_batching_dimensions < rank(lhs)
dot_general
에 정의된 대로
lhs_batching_dimensions
는 텐서이지만 0
및
rank(lhs)
는 스칼라입니다. 암시적 브로드캐스팅을 적용한 후 공식은
[0, ..., 0] <= lhs_batching_dimensions < [rank(lhs), ..., rank(lhs)]
가 됩니다.
이 수식을 특정 dot_general
연산에 적용하면
부울로 구성된 텐서로 평가됩니다. 공식이 제약 조건으로 사용될 때
수식이 true
또는 다음 텐서로 평가되는 경우 제약조건이 유지됩니다.
true
요소만 있습니다.
이름
공식에서 어휘 범위에는 1) 전역 함수, 2) 멤버 정의
3) 로컬 정의 전역 함수 목록은 다음과 같습니다. 목록 프로그램 요소에 따라 달라진다는 것을 적용 대상:
- 연산의 경우 멤버 정의에는 '입력'에 도입된 이름이 포함됩니다. 및 '출력' 섹션으로 이동합니다.
- 그 외 모든 항목의 경우, 멤버 정의에는 구성 요소의 구조적 부분이 포함됩니다.
프로그램 요소로, 해당 EBNF 비단말기의 이름을 딴 것입니다. 대부분
이러한 구조적 부분의 이름은
스네이크 표기법의 비 터미널 이름 (예:
IntegerLiteral
=>)integer_literal
), 이 과정에서 이름이 축약되는 경우도 있습니다 (예:QuantizationStorageType
=>storage_type
)를 사용하며, 이 경우 이름은 '입력'과 명시적으로 유사하게 도입되었습니다. / '출력' 운영 중인 섹션 지정할 수도 있습니다 - 또한 멤버 정의는 항상
self
를 포함하여 찾을 수 있습니다.
값
수식을 평가할 때 다음 유형의 값을 사용할 수 있습니다.
1) Value
(실제 값, 예: dense<[[1, 2], [3, 4]]> : tensor<2x2xi32>
,
항상 자신의 유형을 알고 있음)
2) Placeholder
(미래 가치, 예: lhs
, rhs
또는 result
, 실제값)
값은 아직 알 수 없으며 유형만 알려져 있음)
3) Type
('유형' 섹션에 정의된 유형)
4) Function
('함수' 섹션에 정의된 전역 함수)
컨텍스트에 따라 이름이 다른 값을 참조할 수도 있습니다. 더보기
구체적으로는 '시맨틱' 운영에 대한 섹션 (및 다른 프로그램의 경우 이에 상응하는 항목)
요소)는 런타임 로직을 정의하므로 모든 입력을 Value
로 사용할 수 있습니다.
반면에 '제약 조건'은 작업 (및 그에 상응하는 항목) 섹션은
'compile-time'(컴파일 시간) 즉, 일반적으로 런타임 전에 실행되는 것에 관한 것입니다.
따라서 상수 입력만 Value
로 사용할 수 있고 다른 입력은
Placeholder
(으)로만 제공됩니다.
이름 | '시맨틱'에서 | 'Constraints'에서 |
---|---|---|
전역 함수 | Function |
Function |
상수 입력 | Value |
Value |
상수가 아닌 입력 | Value |
Placeholder |
출력 | Value |
Placeholder |
로컬 정의 | 정의에 따라 다름 | 정의에 따라 다름 |
transpose
작업의 예를 살펴보겠습니다.
%result = "stablehlo.transpose"(%operand) {
permutation = dense<[2, 1, 0]> : tensor<3xi64>
} : (tensor<2x3x2xi32>) -> tensor<2x3x2xi32>
이 작업에서 permutation
는 상수이므로 Value
로 사용할 수 있습니다.
제약 조건을 모두
적용할 수 있어야 합니다 반면에 operand
및 result
는 다음과 같습니다.
시맨틱에서 Value
로 사용할 수 있지만 제약 조건에서는 Placeholder
로만 사용할 수 있습니다.
함수
유형 생성
유형을 구성하는 데 사용할 수 있는 함수는 없습니다. 대신
유형 문법을 사용하는 것이 일반적입니다. 예:
function_type(
[tensor_type([], E), tensor_type([], E)], [tensor_type([], E)])
가 아닌 (tensor<E>, tensor<E>) -> (tensor<E>)
입니다.
유형 함수
element_type
는 텐서 유형과 양자화 텐서 유형에 대해 정의됩니다.TensorElementType
또는QuantizedTensorElementType
가 각각 반환됩니다. 상응하는TensorType
또는QuantizedTensorType
의 부분입니다.
def element_type(x: Value | Placeholder | Type):
if type(x) == TensorType:
return tensor_element_type(x)
if type(x) == QuantizedTensorType:
return quantized_tensor_element_type(x)
if type(x) is not Type:
return element_type(type(x))
is_per_axis_quantized(x: Value | Placeholder | Type) -> Value
바로가기 (is_quantized(x) and quantization_dimension(x) is not None
)is_per_tensor_quantized(x: Value | Placeholder | Type) -> Value
:is_quantized(x) and quantization_dimension(x) is None
의 단축키를 사용합니다.is_promotable(x: Type, y: Type) -> bool
는x
유형을 승격할 수 있는지 확인합니다.y
를 입력합니다.x
및y
이QuantizedTensorElementType
인 경우 프로모션storage_type
에만 적용됩니다. 이 프로모션의 특정 버전은 환원 계산의 컨텍스트에서 현재 사용되고 있는 비율( RFC 참조)
def is_promotable(x: Type, y: Type) -> Value:
is_same_type = (is_bool(x) and is_bool(y)) or
(is_integer(x) and is_integer(y)) or (is_float(x) and is_float(y)) or
(is_complex(x) and is_complex(y)) or
(is_quantized(x) and is_quantized(y) and expressed_type(x) = expressed_type(y))
if is_same_type == False:
return False
if is_integer(x) or is_float(x):
return bitwidth(x) <= bitwidth(y)
if is_complex(x):
return bitwidth(element_type(x)) <= bitwidth(element_type(y))
if is_quantized(x):
return bitwidth(storage_type(x)) <= bitwidth(storage_type(y))
return false
is_quantized(x: Value | Placeholder | Type) -> Value
은(는) 다음 작업의 단축키입니다.is_quantized_tensor_element_type(x)
is_type_name(x: Value | Placeholder | Type) -> Value
모두에게 제공 있습니다. 예를 들어x
이FloatType
이면is_float(x)
는true
를 반환합니다.x
가 값 또는 자리표시자인 경우 이 함수는is_type_name(type(x))
max_value(x: Type) -> Value
는TensorElementType
x
이TensorElementType
이 아니면None
을 반환합니다.min_value(x: Type) -> Value
는TensorElementType
x
이TensorElementType
이 아니면None
을 반환합니다.member_name(x: Value | Placeholder | Type) -> Any
모든 회원이 사용 가능 모든 유형의 정의member_name
입니다. 예:tensor_element_type(x)
상응하는TensorType
의TensorElementType
부분을 반환합니다.x
가 값 또는 자리표시자인 경우 이 함수는member_name(type(x))
x
이 적절한 구성원이 있는 유형이 아닌 경우 이러한 유형의 값이나 자리표시자인 경우None
을 반환합니다.is_empty_algorithm(*args: Type)
는 모든 점 알고리즘 필드가 설정되었는지 확인합니다.None
에게 전송합니다. 이는 도트 알고리즘이 따라서 기본값을 지정하는 것은 잘못된 것입니다.
값 구성
operation_name(*xs: Value | Type) -> Value
모든 작업에 사용할 수 있습니다. 예를 들어add(lhs, rhs)
는 두 개의 텐서 값lhs
과rhs
를 취하고 는 이러한 입력을 사용하여add
연산을 평가한 결과를 반환합니다. 일부 작업의 경우(예:broadcast_in_dim
, 출력 유형은 '부하 발생', 즉 작업을 평가하는 데 필요합니다. 이 경우 함수는 이러한 유형을 인수로 사용합니다.
값에 대한 함수
모든 Python 연산자와 함수를 사용할 수 있습니다. 예: 둘 다 구독 및 슬라이싱 텐서, 양자화 텐서로 색인을 생성하는 데 사용 가능한 Python의 표기법 튜플로 구성됩니다
to_destination_type(x: Value, destination_type: Type) -> Value
정의됨 텐서를 실행하고type(x)
및x
destination_type
는 다음과 같습니다.
def to_destination_type(x: Value, destination_type: Type) -> Value:
if type(x) == destination_type:
return x
if is_quantized(destination_type):
if is_quantized(type(x)):
return quantize(x, destination_type)
assert is_float(type(x))
return quantize(x, destination_type)
if is_quantized(type(x)):
assert destination_type = expressed_type(type(x))
return dequantize(type(x))
return convert(x, destination_type)
convert
, uniform_quantize
및 병합에 대한 초기 토론이 있습니다.
uniform_dequantize
작업 (#1576)
병합 후에는 위의 함수가 필요하지 않으며 작업 이름을 사용할 수 있습니다.
convert
(으)로 대체합니다.
is_nan(x: Value) -> Value
는 텐서에 정의되며 다음 경우true
를 반환합니다.x
의 모든 요소는NaN
또는false
입니다.x
가 텐서가 아닌 경우 은None
를 반환합니다.is_sorted(x: Value) -> Value
는 텐서에 정의되며 다음 경우true
를 반환합니다.x
요소는 오름차순을 기준으로 오름차순으로 정렬됩니다. 색인의 사전순 또는false
입니다.x
가 텐서,None
를 반환합니다.is_unique(x: Value) -> Value
는 텐서에 정의되며x
인 경우true
를 반환합니다. 중복 요소가 없거나 그렇지 않으면false
입니다.x
가 텐서가 아닌 경우 은None
를 반환합니다.member_name(x: Value) -> Any
는 모든 구성원 정의에 대해 정의됨 모든 값의member_name
예를 들어real_part(x)
는RealPart
를 반환합니다. 상응하는ComplexConstant
의 부분입니다.x
가 적절한 멤버가 있으면None
를 반환합니다.same(x: Value) -> Value
는 텐서에 정의되며 다음 경우true
를 반환합니다.x
의 요소는 모두 서로 같거나 그렇지 않은 경우false
입니다. 텐서가 에는 요소가 없으므로 '모두 같음'으로 계산됩니다. 즉, 함수는true
을 반환합니다.x
가 텐서가 아니면None
이 반환됩니다.split(x: Value, num_results: Value, axis: Value) -> Value
정의됨 텐서를 생성하고axis
축을 따라x
의num_results
슬라이스를 반환합니다.x
이 텐서 또는dim(x, axis) % num_results != 0
가 아니면None
이 반환됩니다.is_defined_in_parent_scope(x: Value) -> Value
는 문자열에 정의됩니다.x
이 동일한 범위에 정의된 함수의 이름인 경우true
을 반환합니다. 관련 작업의 상위 함수입니다.is_namespaced_op_name(x: Value) -> Value
는 문자열 및 반환에 대해 정의됨x
가 유효한 작업 이름인 경우true
, 다음과 같은 정규 표현식:[a-zA-Z][a-zA-Z0-9_]*([.][a-zA-Z0-9_$]+)+
셰이프 계산
axes(x: Value | Placeholder | Type) -> Value
은(는) 다음 작업의 단축키입니다.range(rank(x))
dim(x: Value | Placeholder | Type, axis: Value) -> Value
은(는) 다음 작업의 단축키입니다.shape(x)[axis]
dims(x: Value | Placeholder | Type, axes: List) -> List
은(는) 다음 작업의 단축키입니다.list(map(lambda axis: dim(x, axis), axes))
index_space(x: Value | Placeholder | Type) -> Value
는 텐서에서 정의됩니다. 해당TensorType
의size(x)
색인을 다음과 같이 정렬하여 반환합니다. 사전순(예:[0, ..., 0]
,[0, ..., 1]
, ...,shape(x) - 1
x
이 텐서 유형, 양자화 텐서 유형 또는 값이 아닌 경우 또는 이러한 유형 중 하나의 자리표시자인 경우None
를 반환합니다.rank(x: Value | Placeholder | Type) -> Value
은(는) 다음 작업의 단축키입니다.size(shape(x))
shape(x: Value | Placeholder | Type) -> Value
는 'Functions 유형" (member_name
을(를) 통해 전달됨)size(x: Value | Placeholder | Type) -> Value
은(는) 다음 작업의 단축키입니다.reduce(lambda x, y: x * y, shape(x))
양자화 계산
def baseline_element_type(x: Value | Placeholder | Type) -> Type
:element_type(baseline_type(x))
의 단축키를 사용합니다.baseline_type
는 텐서 유형과 양자화 텐서 유형에 대해 정의됩니다. 는 '기준선'으로 변환합니다. 즉, 형태는 동일하지만 요소 유형의 양자화 매개변수가 기본값으로 재설정됩니다. 이것은 텐서 및 양자화 텐서 유형을 비교하는 편리한 트릭으로 사용됨 매우 자주 필요합니다 양자화 유형의 경우 이를 통해 양자화 매개변수를 무시하는 유형 비교, 즉shape
storage_type
,expressed_type
,storage_min
,storage_max
및quantization_dimension
(축당 양자화 유형용)은 모두 일치해야 하지만scales
및zero points
는 다를 수 있습니다.
def baseline_type(x: Value | Placeholder | Type) -> Type:
if type(x) == TensorType:
return x
if type(x) == QuantizedTensorType:
element_type = quantized_tensor_element_type(x)
baseline_element_type = QuantizedTensorElementType(
storage_type = storage_type(element_type),
storage_min = storage_min(element_type),
storage_max = storage_max(element_type),
expressed_type = expressed_type(element_type),
quantization_dimension = quantization_dimension(element_type),
scales = [constant(1.0, expressed_type(element_type))] * dim(x, quantization_dimension(element_type)),
zero_points = [constant(0, storage_type(element_type))] * dim(x, quantization_dimension(element_type)))
return QuantizedTensorType(shape(x), baseline_element_type)
if type(x) is not Type:
return baseline_element_type(type(x))
dequantize
는 양자화 텐서 유형에 정의되어 있으며 이를 다음과 같이 변환합니다. 부동 소수점 텐서 유형을 지원합니다. 이는 양자화 요소를 변환하여 이는 스토리지 유형의 정수 값을 0점과 배율을 사용하여 표현된 유형의 부동 소수점 값 양자화 요소 유형과 관련이 있습니다.
def compute_zero_points(quantized_type, result_type):
if is_per_tensor_quantized(quantized_type):
return broadcast_in_dim(constant(zero_point(quantized_type), storage_type(quantized_type)), [], result_type)
if is_per_axis_quantized(quantized_type):
for i in index_space(result_type):
d = quantization_dimension(quantized_type)
zero_points[i] = zero_points(quantized_type)[i[d]]
return zero_points
def compute_scales(quantized_type, result_type):
if is_per_tensor_quantized(quantized_type):
return broadcast_in_dim(constant(scale(quantized_type), expressed_type(quantized_type)), [],
type(result_type))
if is_per_axis_quantized(quantized_type):
for i in index_space(result_type):
d = quantization_dimension(quantized_type)
scales[i] = scales(quantized_type)[i[d]]
return scales
def dequantize(x: Value) -> Value:
assert is_quantized(x)
x_storage = bitcast_convert(x, storage_type(x))
x_storage_sub = x_storage - compute_zero_points(type(x), type(x_storage))
x_expressed_sub = convert(x_storage_sub, expressed_type(x))
return x_expressed_sub * compute_scales(type(x), type(x_expressed_sub))
quantize
는 부동 소수점 텐서 유형에서 정의되며 이를 다음과 같이 변환합니다. 양자화 텐서 유형을 기반으로 합니다. 이는 부동 소수점 값의 변환을 통해 발생합니다. 표현된 유형의 정수 값을 스토리지 유형의 해당 정수 값으로 변환합니다. 를 사용합니다.
def quantize(x: Value, result_type: Type) -> Value:
assert is_float(x) and is_quantized(result_type)
zero_points = compute_zero_points(result_type, TensorType(shape(x), storage_type(result_type)))
converted_zero_points = convert(zero_points, expressed_type(result_type))
converted_min = convert(storage_min(result_type), expressed_type(result_type))
converted_max = convert(storage_max(result_type), expressed_type(result_type))
x_scaled = x / compute_scales(result_type, type(x))
x_scaled_add_zp = x_scaled + converted_zero_points
x_clamped = clamp(converted_min, x_scaled_add_zp, converted_max)
x_rounded = round_nearest_even(x_clamped)
return convert(x_rounded, result_type)
dequantize_op_quantize
는 요소별 계산을 지정하는 데 사용됩니다. 양자화 텐서에 대해 학습합니다. 이는 비양자화, 즉 양자화된 요소를 연산을 실행한 다음 양자화(즉, 턴 방식)를 결과를 스토리지 유형으로 반환합니다 현재 이 함수는 텐서당 양자화에 적합합니다 축당 양자화 작업 진행 중 (#1574)
def dequantize_op_quantize(op, *inputs_and_output_type):
inputs = inputs_and_output_type[:-1]
output_type = inputs_and_output_type[-1]
float_inputs = map(dequantize, inputs)
float_result = op(*float_inputs)
return quantize(float_result, output_type)
def dequantize_batch_norm_grad_or_training_quantize(op, *inputs_and_output_types):
inputs = inputs_and_output_type[:-3]
float_inputs = map(dequantize, inputs)
float_results = op(*float_inputs)
return map(quantize, float_results, inputs_and_output_type[-3:])
def dequantize_compare(lhs, rhs, comparison_direction):
float_lhs = dequantize(lhs)
float_rhs = dequantize(rhs)
return compare(float_lhs, float_rhs, comparison_direction, FLOAT)
def dequantize_select_quantize(pred, on_true, on_false, output_type):
float_on_true = dequantize(on_true)
float_on_false = dequantize(on_false)
float_result = select(pred, float_on_true, float_on_false)
return quantize(float_result, output_type)
hybrid_dequantize_then_op
는 부동 소수점에 lhs를, 양자화된 유형으로 rhs를 허용하는 하이브리드 연산입니다. 그것은 양자화된 입력을 표현된 유형으로 역양자화하고 계산을 수행 플로팅입니다. float lhs 텐서의 요소 유형 및 표현된 양자화 rhs 유형 텐서가 동일해야 합니다.
def hybrid_dequantize_then_op(op, lhs, rhs):
assert(is_float(lhs) and is_quantized(rhs) and element_type(lhs) == expressed_type(rhs))
return op(lhs, dequantize(rhs))
그리드 계산
cross_partition(replica_groups: Value) -> Value
자세한 내용은 'cross_replica'를 참조하세요. 섹션을 참조하세요.cross_replica(replica_groups: Value) -> Value
자세한 내용은 'cross_replica'를 참조하세요. 섹션을 참조하세요.cross_replica_and_partition(replica_groups: Value) -> Value
자세한 내용은 "cross_replica_and_partition" 섹션을 참조하세요.flattened_ids(replica_groups: Value) -> Value
자세한 내용은 'Flattened_ids'를 참조하세요. 섹션을 참조하세요.
역동주의
StableHLO 값은 tensor<?xi64>
하지만 StableHLO 값은 동적 측정기준 (순위가 지정되지 않음)을 가질 수
활력주의(예: tensor<*xi64>
)을 입력합니다. 피연산자 및 결과는 동적
치수에 대한 제약이 있더라도 치수를 변경할 수 없습니다. 제약 조건은
정적으로 확인되어야 하며, 그렇지 않으면 런타임 및
일치하지 않으면 정의되지 않은 동작이 발생합니다. 아래에서 예를 확인하세요.
단항 요소 연산의 셰이프 불일치
다음 장난감 프로그램을 생각해 보세요.
func.func @foo(%arg0: tensor<?xf64>) {
%0 = stablehlo.abs %arg0 : (tensor<?xf64>) -> tensor<2xf64>
return
}
이러한 프로그램은 특이합니다. 왜냐하면 그것의 형태를 아는 것이 일반적이지 않기 때문입니다.
입력의 형태가 아니라 결과입니다. 하지만 유효한 StableHLO입니다.
있습니다. 여기서는 abs
작업을 정적으로 검증할 수 없습니다.
피연산자의 정확한 형태를 알 수 없기 때문입니다. 그러나 도형은
이는 확실히 호환되며 정적으로 확인할 수 있습니다. ?
가
런타임 시 2
가 되고 아무런 문제가 없습니다. 하지만 ?
에서는 다음을 수행할 수 있습니다.
다른 정수로 밝혀지며, 이 경우 동작이 정의되지 않습니다.
결과에서 측정기준 크기가 동적인 경우 정의할 수 없습니다. 실제로 '예상'은 없습니다 따라서 A, B, C, D 등이 일치하지 않습니다.
이진 요소별 연산의 셰이프 불일치
다음 장난감 프로그램을 생각해 보세요.
func.func @foo(%arg0: tensor<?xf64>, %arg1: tensor<?xf64>) {
%0 = stablehlo.add %arg0, %arg0 : (tensor<?xf64>, tensor<?xf64>) -> tensor<?xf64>
return
}
이진 요소별 연산에서 입력의 모양과 결과가 런타임에 일치해야 합니다. 컴파일 시 정적 차원은 다음과 같아야 합니다. 그렇지 않으면 호환되기만 하면 됩니다. 입력에 동적 측정기준이 있는 경우 정의되지 않은 측정기준이 있을 수 있습니다. 동적 크기가 해당하는 광고 크기와 일치하지 않을 수 있기 때문에 다른 피연산자의 크기 (정적 또는 동적) 모든 입력이 정적인 경우 결과가 동적인지 여부는 중요하지 않습니다. 정적으로 알려진 측정기준은 정적으로 확인되며 동적 측정기준은 제약 조건을 적용할 수도 있습니다
출력 형태를 피연산자로 취하는 작업의 형태 불일치
다음 장난감 프로그램을 생각해 보세요.
func.func @foo(%arg0: tensor<2xi32>) {
%0 = stablehlo.dynamic_iota %arg0, dim = 0 : (tensor<2xi32>) -> tensor<3x4xi64>
return
}
런타임 시 셰이프 피연산자의 값은 결과의 셰이프와 일치해야 합니다.
그렇지 않으면 동작이 정의되지 않습니다. 즉, 런타임 시 %arg0
에는
dense<[3, 4]> : tensor<2xi32>
입니다. 셰이프 피연산자가 상수인 경우
정적으로 확인할 수 있습니다 결과 도형이 완전히 동적이면
불일치일 수 없습니다.