Boost logo

Boost :

Subject: Re: [boost] Going forward with Boost.SIMD
From: Mathias Gaunard (mathias.gaunard_at_[hidden])
Date: 2013-04-20 05:51:47

On 19/04/13 00:29, Marc Glisse wrote:
> On Thu, 18 Apr 2013, Mathias Gaunard wrote:
>> Development of Boost.SIMD will still proceed, aiming for integration
>> in Boost, but standardization appears to be definitely out of the
>> question.
>> Any feedback of the API presented in the proposal is welcome.
>> <>
> Copying here my earlier comments so they are in the same place as others'.
> Some of them are only relevant for standardization, not for a boost
> library.

I wasn't subscribed to c++-lib-ext at the time, so I missed them.

> Hello,
> a few comments while reading N3571.
> pack<T,N> seems more similar to std::array than std::tuple to me.

It's statically-sized, so both runtime and compile-time access are possible.
Compile-time access could be significantly more efficient.

> We
> could even dream of merging pack and array into a single type.

I don't think that's a good idea, pack has a very strong numerical
semantic. You don't really want to do +, * or / on arrays.
Plus pack<T, N> requires N to be a power of 2.

> As much as possible, I would like to avoid having a different interface
> for vectors and scalars. We have std::min for scalars, we can overload
> it for vectors instead of having simd::min.

The idea is that any SIMD code should be valid scalar code as well.
I'm not sure whether we want the selection for functions to use ADL or
whether it should be std::min. I have no strong opinion on this.

> We have ?: for scalars, you
> don't need to restrict yourself to a pure library

Overloading ?: would probably have to be a standalone language extension
to core no?

> Masking: it is a bit strange to be able to do pack<double> & int but not
> double & int. Currently in gcc we require that you (reinterpret) cast
> the pack<double> to a pack<some integer>, do the masking and go back.

It was a wish from my colleague; I personally think it might be better
to align the pack operators to be the same as the scalar equivalents,
and therefore not allow it without a cast.

> Any policy on reinterpret_cast-ing a pack to a pack of a different type?

In Boost.SIMD there is a bitwise_cast<To>(from) function, which is
essentially the same as
To to;
memcpy(&to, &from, sizeof(from));
return to;

This can be optimized to a reinterpret_cast in some cases, but
reinterpret_cast itself is dangerous because of aliasing issues.

ass T , std :: size_t N = unspecified >
> struct alignas ( sizeof ( T ) * N ) pack
> Do you really want to specify that large an alignment? You give examples
> with N=100...

N can never be 100, it's a power of 2.
It would be possible to relax the alignment requirement somewhat however.

> Maybe operator[] const could return by value if it wants to?


> Since the splat constructor is implicit, you may not need to document
> all the mixed operations.

It was to make things clearer, but I guess it might not be necessary.

> Any notion of a subvector?

No, though it would probably be useful to be able to split any vector in
two. Duly noted.

> For gather and others, the proposal accepts mixing vector sizes.

For scatter/gather, it doesn't accept a number of indices different than
the size of the vectors being loaded.
Conversions are allowed to happen however, you can load from a uint8* to
a vector of int32.

> cmath functions: it is not clear what signatures are supported, in
> particular for functions that use several types (ldexp has double and
> int). The list doesn't seem to exactly match cmath, actually. frexp
> takes an int*, does the vector version take a pointer to a vector, or
> some scatter-like vector?

We have some equivalents in Boost.SIMD, to make things simpler we use
int32 for float and int64 for double, so that the sizes of vectors are
the same.

> Traits: are those supposed to be template aliases? Or to derive from
> what they are supposed to "return"? Or have a typedef ... type; inside?

They're metafunctions, i.e. classes with a type member typedef.

> For transform and accumulate, I have seen other proposals that specify
> new versions more in terms of permissions (what the compiler is allowed
> to do) and less implementation. Depending on the tag argument you pass
> to transform/accumulate, you give the compiler permission to reorder the
> operations, or do other transformations and it then deduces that it can
> parallelize and/or vectorize. Looks nice. Note that it doesn't
> contradict this proposal, simd::transform can always forward to
> std::transform(..., vectorizable_tag()) (or in the reverse direction).

simd::transform takes a function object that must be valid with both
scalar and pack values; std::transform only requires that the function
object be valid with scalar values.
That's the main difference between the two functions.

Boost list run by bdawes at, gregod at, cpdaniel at, john at