Namespaces
Variants

Data-parallel types (SIMD) (since C++26)

From cppreference.net

이 라이브러리는 데이터 병렬 타입과 이러한 타입에 대한 연산을 제공합니다: 사용 가능한 경우 데이터 병렬성을 명시적으로 표현하고 데이터 병렬 실행 리소스를 통해 데이터를 구조화하기 위한 이식 가능한 타입으로, 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

목차

주요 클래스

데이터 병렬 벡터 타입
(클래스 템플릿)
basic_simd 의 너비를 지정할 수 있는 편의 앨리어스 템플릿
(앨리어스 템플릿)
요소 타입이 bool 인 데이터 병렬 타입
(클래스 템플릿)
basic_simd_mask 의 너비를 지정할 수 있는 편의 앨리어스 템플릿
(앨리어스 템플릿)

로드 및 저장 플래그

데이터 병렬 타입을 위한 로드 및 스토어 플래그
(클래스 템플릿)
로드 및 스토어 연산에 사용되는 기본 플래그
(상수)
로드 및 스토어 연산에서 값 보존이 아닌 변환을 활성화하는 플래그
(상수)
로드-스토어 주소가 특정 저장소에 대해 datapar::alignment 값으로 정렬되었음을 나타내는 플래그
(상수)
로드-스토어 주소가 특정 저장소에 대해 지정된 정렬로 정렬되었음을 나타내는 플래그
(변수 템플릿)

로드 및 스토어 연산

연속 범위의 요소들을 basic_simd 로 로드합니다
(함수 템플릿)
basic_simd 의 요소들을 연속 범위에 저장합니다
(함수 템플릿)

캐스트

단일 데이터-병렬 객체를 여러 개로 분할
(함수 템플릿)
여러 데이터-병렬 객체를 단일 객체로 연결
(함수 템플릿)

알고리즘

basic_simd 에 대한 요소별 최소/최대 연산
(함수 템플릿)
basic_simd 에 대한 요소별 clamp 연산
(함수 템플릿)
조건부 연산자를 사용한 요소별 선택
(함수 템플릿)

리덕션

basic_simd 의 모든 값을 지정된 이항 연산을 통해 단일 값으로 축소
(함수 템플릿)
basic_simd_mask bool 로의 축소
(함수 템플릿)
basic_simd_mask true 값 개수로의 축소
(함수 템플릿)
basic_simd_mask 의 첫 번째 또는 마지막 true 값의 인덱스로의 축소
(함수 템플릿)

Traits

datapar::flag_aligned 에 적합한 정렬을 획득함
(클래스 템플릿)
데이터 병렬 타입의 요소 타입을 변경함
(클래스 템플릿)
데이터 병렬 타입의 너비를 변경함
(클래스 템플릿)

수학 함수

<cmath> <complex> 헤더의 모든 함수들은 basic_simd 에 대해 오버로드됩니다.

비트 조작 함수

<bit> 헤더의 모든 비트 조작 함수들은 basic_simd 에 대해 오버로드되어 있습니다.

구현 세부 사항

ABI 태그

데이터 병렬 타입 basic_simd basic_simd_mask ABI 태그  와 연관되어 있습니다. 이러한 태그들은 데이터 병렬 객체의 크기와 이진 표현을 지정하는 타입들입니다. 이 설계는 대상 아키텍처와 컴파일러 플래그에 따라 크기와 이진 표현이 달라지도록 의도되었습니다. ABI 태그는 요소 타입과 함께 너비를 결정합니다.

ABI 태그는 머신 명령어 집합 선택과 독립적으로 유지됩니다. 선택된 머신 명령어 집합은 사용 가능한 ABI 태그 유형을 제한합니다. ABI 태그를 통해 사용자는 데이터 병렬 타입 객체를 번역 단위 경계를 넘어 안전하게 전달할 수 있습니다.

설명 전용 엔티티

using /*simd-size-type*/ = /* 설명 참조 */ ;
(1) ( 설명 전용* )
template < std:: size_t Bytes >
using /*integer-from*/ = /* 설명 참조 */ ;
(2) ( 설명 전용* )
template < class T, class Abi >
constexpr /*simd-size-type*/ /*simd-size-v*/ = /* 설명 참조 */ ;
(3) ( 설명 전용* )
template < class T >
constexpr std:: size_t /*mask-element-size*/ = /* 설명 참조 */ ;
(4) ( 설명 전용* )
template < class T >
concept /*constexpr-wrapper-like*/ = /* 설명 참조 */ ;
(5) ( 설명 전용* )
template < class T >
using /*deduced-simd-t*/ = /* 설명 참조 */ ;
(6) ( 설명 전용* )
template < class V, class T >
using /*make-compatible-simd-t*/ = /* 설명 참조 */ ;
(7) ( 설명 전용* )
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 > 는 다음과 동등한 별칭이다:
  • decltype ( x + x ) , 만약 x + x 의 타입이 basic_simd 의 활성화된 특수화인 경우; 그렇지 않으면
  • void .
7) x const T 타입의 lvalue라고 하자. /*make-compatible-simd-t*/ < V, T > 는 다음과 동등한 별칭이다:
  • /*deduced-simd-t*/ < T > , 해당 타입이 void 가 아닌 경우, 그렇지 않으면
  • std :: datapar :: simd < decltype ( x + x ) , V​ :: ​size ( ) > .
수학 함수 요구사항
template < class V >
concept /*simd-floating-point*/ = /* see description */ ;
(8) ( 설명 전용* )
template < class ... Ts >
concept /*math-floating-point*/ = /* see description */ ;
(9) ( 설명 전용* )
template < class ... Ts >

requires /*math-floating-point*/ < Ts... >

using /*math-common-simd-t*/ = /* see description */ ;
(10) ( 설명 전용* )
template < class BinaryOp, class T >
concept /*reduction-binary-operation*/ = /* see description */ ;
(11) ( 설명 전용* )
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... > 는 다음과 동등한 별칭이다:
  • /*deduced-simd-t*/ < T0 > , 단 sizeof... ( Ts ) == 1 true 인 경우
  • 그렇지 않고, std:: common_type_t < /*deduced-simd-t*/ < T0 > , /*deduced-simd-t*/ < T1 >> , 단 sizeof... ( Ts ) == 2 true 이고 /*math-floating-point*/ < T0 > && /*math-floating-point*/ < T1 > true 인 경우
  • 그렇지 않고, std:: common_type_t < /*deduced-simd-t*/ < T0 > , T1 > , 단 sizeof... ( Ts ) == 2 true 이고 /*math-floating-point*/ < T0 > true 인 경우
  • 그렇지 않고, std:: common_type_t < T0, /*deduced-simd-t*/ < T1 >> , 단 sizeof... ( Ts ) == 2 true 인 경우
  • 그렇지 않고, std:: common_type_t < /*math-common-simd-t*/ < T0, T1 > , TRest... > , 단 /*math-common-simd-t*/ < T0, T1 > 가 유효한 타입인 경우
  • 그렇지 않으면, std:: common_type_t < /*math-common-simd-t*/ < TRest... > , T0, T1 > .
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 > 는 다음 조건을 만족할 때만 모델링됩니다:

  • BinaryOp 는 교환 법칙을 만족하는 이진 요소별 연산이며,
  • BinaryOp 타입의 객체는 지정되지 않은 ABI 태그 Abi 에 대해 std :: datapar :: basic_simd < T, Abi > 타입의 두 인수로 호출 가능하며, std :: datapar :: basic_simd < T, Abi > 를 반환합니다.
SIMD ABI 태그
template < class T >
using /*native-abi*/ = /* see description */ ;
(12) ( 설명 전용* )
template < class T, /*simd-size-type*/ N >
using /*deduce-abi-t*/ = /* see description */ ;
(13) ( 설명 전용* )
12) /*native-abi*/ < T > 는 ABI 태그에 대한 구현-정의 별칭입니다. 이것은 효율적인 명시적 벡터화를 위해 사용할 기본 ABI 태그입니다. 결과적으로, basic_simd < T, /*native-abi*/ < T >> 는 활성화된 특수화입니다.
13) /*deduce-abi-t*/ < T, N > 는 다음 조건을 만족하는 ABI 태그 타입을 지칭하는 별칭입니다:
  • /*simd-size-v*/ < T, /*deduce-abi-t*/ < T, N >> N 과 동일하고,
  • std :: datapar :: basic_simd < T, /*deduce-abi-t*/ < T, N >> 가 활성화된 특수화이며,
  • std :: datapar :: basic_simd_mask < sizeof ( T ) , /*deduce-abi-t*/ < /*integer-from*/ < sizeof ( T ) > , N >> 가 활성화된 특수화인 경우.
이는 T 가 벡터화 가능한 타입이고 N > 0 && N <= M true 인 경우에만 정의됩니다. 여기서 M 은 최소 64 이상이며 T 에 따라 달라질 수 있는 구현 정의 최댓값입니다.
로드 및 저장 플래그
struct /*convert-flag*/ ;
(14) ( 설명 전용* )
struct /*aligned-flag*/ ;
(15) ( 설명 전용* )
template < std:: size_t N >
struct /*overaligned-flag*/ ;
(16) ( 설명 전용* )
14-16) 이러한 태그 유형들은 std::datapar::flags 의 템플릿 인자로 사용됩니다. 해당 사용법에 대해서는 load and store flags 를 참조하십시오.

참고 사항

기능 테스트 매크로 표준 기능
__cpp_lib_simd 202411L (C++26) 데이터 병렬 타입 및 연산
__cpp_lib_simd_complex 202502L (C++26) std::datapar::simd 내 인터리브 복소수 값 지원

예제

#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

참고 항목

수치 배열, 배열 마스크 및 배열 슬라이스
(클래스 템플릿)

외부 링크

1. ISO/IEC TS 19570:2018 Section 9 "Data-Parallel Types"의 구현 — github.com
2. TS 구현 진행 상황: GCC/libstdc++ ( std::experimental::simd 는 GCC-11과 함께 배포됨) — gcc.gnu.org