Data-parallel types (SIMD) (since C++26)
이 라이브러리는 데이터 병렬 타입과 이러한 타입에 대한 연산을 제공합니다: 사용 가능한 경우 데이터 병렬성을 명시적으로 표현하고 데이터 병렬 실행 리소스를 통해 데이터를 구조화하기 위한 이식 가능한 타입으로, SIMD 레지스터 및 명령어나 공통 명령어 디코더에 의해 구동되는 실행 유닛과 같은 리소스를 포함합니다.
벡터화 가능 타입 집합은 다음으로 구성됩니다:
- 모든 표준 정수 및 문자 타입;
- 대부분의 부동소수점 타입 포함: float , double , 그리고 선택된 확장 부동소수점 타입: std:: float16_t , std:: float32_t , 그리고 std:: float64_t (정의된 경우); 그리고
-
std::
complex
<
T
>
여기서
T는 벡터화 가능한 부동소수점 타입입니다.
데이터 병렬 타입 은 요소 타입 이라고 하는 기본 벡터화 가능 타입의 하나 이상의 요소로 구성됩니다. 요소의 개수는 너비 라고 하며, 각 데이터 병렬 타입에 대해 상수입니다.
데이터 병렬 타입은 클래스 템플릿
basic_simd
와
basic_simd_mask
의 모든 활성화된 특수화를 의미합니다.
데이터 병렬 타입의
데이터 병렬 객체
는
T
타입의 객체와 유사하게 동작합니다. 하지만
T
가 단일 값을 저장하고 조작하는 반면,
T
를 요소 타입으로 하는 데이터 병렬 타입은 여러 값을 저장하고 조작합니다.
데이터 병렬 객체의 모든 연산은 객체의 각 요소 또는 두 객체의 해당 요소에 적용되는 요소별(element-wise) 방식으로 작동합니다(감소 연산과 같은 수평 연산은 명시적으로 표시된 경우 제외). 각각의 이러한 적용은 다른 적용과 순서가 지정되지 않습니다. 이 간단한 규칙은 데이터 병렬성을 표현하며 컴파일러가 SIMD 명령어 및/또는 독립적인 실행 스트림을 생성하는 데 사용됩니다.
데이터 병렬 객체에 대한 모든 연산(비- constexpr 수학 함수 오버로드 제외)은 constexpr 입니다: 상수 표현식 평가에서 데이터 병렬 객체를 생성하고 사용하는 것이 가능합니다.
별칭 템플릿
simd
과
simd_mask
는 사용자가 특정 크기로 너비를 지정할 수 있도록 정의됩니다. 기본 너비는 컴파일 시점에 구현에 의해 결정됩니다.
|
헤더에 정의됨
<simd>
|
|
|
네임스페이스에 정의됨
std::datapar
|
목차
주요 클래스
로드 및 저장 플래그
로드 및 스토어 연산
캐스트
알고리즘
리덕션
순열
Traits
수학 함수
<cmath>
및
<complex>
헤더의 모든 함수들은
비트 조작 함수<bit>의 모든 비트 조작 함수(std::bit_cast 제외)는
구현 세부 사항ABI 태그
데이터 병렬 타입
ABI 태그는 머신 명령어 집합 선택과 독립적으로 유지됩니다. 선택된 머신 명령어 집합은 사용 가능한 ABI 태그 유형을 제한합니다. ABI 태그를 통해 사용자는 데이터 병렬 타입 객체를 번역 단위 경계를 넘어 안전하게 전달할 수 있습니다.
설명 전용 엔티티
1)
/*simd-size-type*/
는 부호 있는 정수 타입에 대한 별칭입니다. 구현체는 어떤 부호 있는 정수 타입이든 자유롭게 선택할 수 있습니다.
2)
/*integer-from*/
<
Bytes
>
는 부호 있는 정수 타입
T
의 별칭으로,
sizeof
(
T
)
가
Bytes
와 동일한 경우를 의미합니다.
3)
/*simd-size-v*/
<
T, Abi
>
는 활성화된 특수화
basic_simd<T, Abi>
의 너비를 나타내며, 그렇지 않을 경우
0
을 나타냅니다.
4)
만약
T
가
std
::
datapar
::
basic_simd_mask
<
Bytes, Abi
>
를 나타낸다면,
/*mask-element-size*/
<
T
>
는
Bytes
와 같습니다.
5)
/*constexpr-wrapper-like*/
개념은 다음과 같이 정의됩니다:
template< class T > concept /*constexpr-wrapper-like*/ = std::convertible_to<T, decltype(T::value)> && std::equality_comparable_with<T, decltype(T::value)> && std::bool_constant<T() == T::value>::value && std::bool_constant<static_cast<decltype(T::value)>(T()) == T::value>::value;
6)
x
를
const
T
타입의 lvalue라고 하자.
/*deduced-simd-t*/
<
T
>
는 다음과 동등한 별칭이다:
7)
x
를
const
T
타입의 lvalue라고 하자.
/*make-compatible-simd-t*/
<
V, T
>
는 다음과 동등한 별칭이다:
8)
개념
/*simd-floating-point*/
는 다음과 같이 정의됩니다:
template< class V > concept /*simd-floating-point*/ = std::same_as<V, std::datapar::basic_simd<typename V::value_type, typename V::abi_type>> && std::is_default_constructible_v<V> && std::floating_point<typename V::value_type>;
9)
개념
/*math-floating-point*/
는 다음과 같이 정의됩니다:
template< class... Ts > concept /*math-floating-point*/ = (/*simd-floating-point*/</*deduced-simd-t*/<Ts>> || ...);
10)
T0
가
Ts...
[
0
]
를 나타내고,
T1
이
Ts...
[
1
]
를 나타내며,
TRest
가
T0, T1, TRest...
가
Ts...
와 동등하도록 하는 팩을 나타낸다고 하자. 그러면
/*math-common-simd-t*/
<
Ts...
>
는 다음과 동등한 별칭이다:
11)
/*reduction-binary-operation*/
개념은 다음과 같이 정의됩니다:
template< class BinaryOp, class T > concept /*reduction-binary-operation*/ = requires (const BinaryOp binary_op, const std::datapar::simd<T, 1> v) { { binary_op(v, v) } -> std::same_as<std::datapar::simd<T, 1>>; }; /*reduction-binary-operation*/ < BinaryOp, T > 는 다음 조건을 만족할 때만 모델링됩니다:
12)
/*native-abi*/
<
T
>
는 ABI 태그에 대한 구현-정의 별칭입니다. 이것은 효율적인 명시적 벡터화를 위해 사용할 기본 ABI 태그입니다. 결과적으로,
basic_simd
<
T,
/*native-abi*/
<
T
>>
는 활성화된 특수화입니다.
13)
/*deduce-abi-t*/
<
T, N
>
는 다음 조건을 만족하는 ABI 태그 타입을 지칭하는 별칭입니다:
T
가 벡터화 가능한 타입이고
N
>
0
&&
N
<=
M
가
true
인 경우에만 정의됩니다. 여기서
M
은 최소
64
이상이며
T
에 따라 달라질 수 있는 구현 정의 최댓값입니다.
참고 사항
예제
이 코드 실행
#include <iostream> #include <simd> #include <string_view> void println(std::string_view name, auto const& a) { std::cout << name << ": "; for (std::size_t i{}; i != a.size(); ++i) std::cout << a[i] << ' '; std::cout << '\n'; } template<class A> constexpr std::datapar::basic_simd<int, A> my_abs(std::datapar::basic_simd<int, A> x) { return std::datapar::select(x < 0, -x, x); } int main() { constexpr std::datapar::simd<int> a = 1; println("a", a); constexpr std::datapar::simd<int> b([](int i) { return i - 2; }); println("b", b); constexpr auto c = a + b; println("c", c); constexpr auto d = my_abs(c); println("d", d); constexpr auto e = d * d; println("e", e); constexpr auto inner_product = std::datapar::reduce(e); std::cout << "inner product: " << inner_product << '\n'; constexpr std::datapar::simd<double, 16> x([](int i) { return i; }); println("x", x); // overloaded math functions are defined in <simd> println("cos²(x) + sin²(x)", std::pow(std::cos(x), 2) + std::pow(std::sin(x), 2)); } 출력: a: 1 1 1 1 b: -2 -1 0 1 c: -1 0 1 2 d: 1 0 1 2 e: 1 0 1 4 inner product: 6 x: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 cos²(x) + sin²(x): 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 참고 항목
|