std::simd
Created: 2023-11-08 Wed 11:25
std::simd
std::simd
coherence with standard c++simd
interfacestd::byte
simd
as a rangestd::simd
constexpr simd() noexcept; //does not initialize template<class U> constexpr simd(U&& value) noexcept; //broadcast template<class U, class UAbi> constexpr explicit simd(const simd<U, UAbi>&) noexcept; template<class G> constexpr explicit simd(G&& gen) noexcept; template<contiguous_iterator It, class Flags = element_aligned_tag> constexpr simd(const It& first, Flags = {}) template<class U, class Flags = element_aligned_tag> void copy_from(const U* mem, Flags = {}) && template<class U, class Flags = element_aligned_tag> void copy_to(U* mem, Flags = {}) const &&;
#include <experimental/simd> namespace stdx = std::experimental; using intv8 = stdx::fixed_size_simd<int,8>; intv8 add_v(const intv8& a, const intv8& b) { return a + b; } int main() { int a_data[] = {1, 2, 3, 4, 5, 6, 7, 8}; intv8 a; a.copy_from(&a_data[0], stdx::element_aligned); int b_data[] = {7, 6, 5, 4, 3, 2, 1, 0}; intv8 b; b.copy_from(&b_data[0], stdx::element_aligned); intv8 c = add_v( a, b ); for (int i=0; i< c.size(); i++) { int val = c[i]; print("{} ", val); } }
copy_from
and continguous_iterator
api
[it, it + size)
must be a valid rangeT x;
doesn't, T x();
zero-initializesarray
, c array, span
, ~initializerlist~v
initializer_list
interacts poorly with broadcast constructornamespace stdx = std::experimental; using simd_int_8 = stdx::fixed_size_simd<int,8>; std::array<int, 8> data = {0, 1, 2, 3, 4, 5, 6, 7}; simd_int_8 simd1{data}; std::span<int, 8> sdata{data}; simd_int_8 simd2{sdata}; int cdata[] = {0, 1, 2, 3, 4, 5, 6, 7}; simd_int_8 simd3{cdata}; simd_int_8 simd4 = {0, 1, 2, 3, 4, 5, 6, 7}; // initializer list*
vector<data-parallel-type>
string
and string_view
span<data-parallel-type>
namespace stdx = std::experimental; using simd_int_8 = stdx::fixed_size_simd<int,8>; std::vector<int> vdata = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; simd_int_8 simd1{data}; //drops 8, 9 std::span<int> data{vdata}; simd_int_8 simd2{sdata}; //drops 8, 9 std::string s{"hello"); simd_int_8 simd3{s}; //default initialize remaining
copy_from
template<contiguous_range R, class Flags = element_aligned_tag> constexpr simd(R&& r, Flags = {}) template<contiguous_range R, class Flags = element_aligned_tag> constexpr copy_from(R&& r, Flags = {}) template<contiguous_iterator It, class Flags = element_aligned_tag> constexpr simd( simdunchecked_t{}, const It& first, Flags = {}) template<contiguous_iterator It, class Flags = element_aligned_tag> constexpr unsafe_copy_from ( const It& first, Flags = {})
vector<simd>
is something we needstd::simd<int> simd, simd2; auto simd_result = simd + simd2; //opt in to unitialized? std::simd<int> simd { simdunchecked_t{} };
initializer_list
out in coresimd<int> a(1); // [1, 1, 1, 1] simd<int> b{1}; // [1, 1, 1, 1] simd<int> c = {1}; // [1, 1, 1, 1] simd<int> d{1, 0}; // [1, 0, 0, 0] simd<int> e = {1, 0}; // [1, 0, 0, 0] // alternate simd<int> a(1); // [1, 0, 0, 0] simd<int> b{1}; // [1, 0, 0, 0] simd<int> c = {1}; // [1, 0, 0 ,0] simd<int> d{1, 2}; // [1, 2, 0, 0] simd<int> e = {1, 2}; // [1, 2, 0, 0] simd<int> f(bcast(1)); // [1, 1, 1, 1] simd<int> b = bcast(1); // [1, 1, 1, 1]
std::byte
std::byte
is a safer unsigned char
for bitopsspan<byte>
Operator[]
and proxy referenceoperator[]
confusingvector<bool>
)get
and set
operator[]
when we can make it work well everywhereconstexpr reference operator[](simd-size-type) &; constexpr value_type operator[](simd-size-type) const&
begin
end
iterators
simd
and simd_mask
reduce_count
-> count_if_true
reduce_min_index
-> find_if_true
operator==
and operator!=
operator<
, operator>
etcxsimd
does this and calls them eq
, neq
, gt
, etccurrent | regular |
minimal change with existing scalar alg to work with simd | fundamental regular operations have an exclusive meaning in c++ (aside from valarray) |
minimize cognitive overhead when learning simd | vector<simd<T>> is a use case and operator== works works |
discoverability - if you say if (simd == simd ) compile fail |
default of operator== works with simd data members -secondary use case of simd can make use of existing generic algorithms |