# SE-0229 — SIMD Vectors

**URL:** <https://forums.swift.org/t/se-0229-simd-vectors/16518>\
**Category:** Proposal Reviews\
**Created:** [September 27, 2018, 5:27pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518 "2018-09-27T17:27:15Z")\
**Posts on this page:** 20\
**Page:** 3

<div class="post-metadata">

**Author:** ![scanon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/scanon/32/2445_2.png) [@scanon](https://forums.swift.org/u/scanon)\
**Post date:** [October 3, 2018, 2:00pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518/44 "2018-10-03T14:00:54Z")

</div>

> [@00buggy00](#):
>
> In some ways yes, and in some ways no. As mentioned previously on this thread and on the discussion thread, the naming convention does not feel very much like Swift. The author's argument for not going with Vector4, for example, is not very strong and he even concedes that there "[...] should not [be] any performance consequences [...]". Though I agree that this implementation may induce some added complexity, I think it is worth it to maintain the Swift API feel for users--most users are not going to care what the API looks like under the hood, but they are going to expect the language to maintain Swift naming conventions. So, I strongly echo the sentiments written above by previous reviewers.

Hi 00buggy00 -- can you clarify what you mean by "Swift feel"? You use that term in a few places, but other than `Vector4<Float>`, you don't really offer any alternatives of what you think would have more "Swift feel", so it's a little bit hard to see what you're getting at.

To me, `Vector4<Float>` vs `Float.Vector4` is basically "colour" vs "color". Neither feels especially more "Swift" to me--one is the free spelling and the other the member spelling. "Swift" for me is more about what the language lets you do and the safety that it gives you. `simd_float4` is not-very-swift, because it doesn't follow the conventions and doesn't enable generic code.

The reason I personally prefer `Float.Vector4` is that it's not fighting the language; I don't mind the extra boilerplate, but I think that we should encourage styles that minimize the boilerplate for users who copy the style of the standard library in their own code. With the language as it stands today, that makes me lean towards `Float.Vector4`. If you all feel really strongly about `Vector4<Float>`, I'm OK with that, but I hope that you'll push just as hard for the language features that would actually make that the natural spelling.

> [@](#):
>
> If the previously mentioned naming convention were used, you wouldn't need a `count` method as you already known how many values are in the vector.

As mentioned before, there is no information that `Vector4<Float>` has but `Float.Vector4` does not. Both types know that they have precisely 4 elements. These are essentially equivalent formulations. It is OK to prefer one or the other on style grounds, but many of the arguments that I've seen advanced claim that one lets us do something that the other does not. I am yet to see any example where this is actually the case.

In this case, the `count` property is still useful in both instances to enable writing code that is generic over vector length. It exists because over the course of a few months writing code against prototypes of this proposal, I found that it was necessary.

Ditto subscripting. It is not a vestigial limb of `Collection`, but rather a key escape valve for writing real code. Absent `Collection` conformance, `count` and `subscript` are the tools we have to iterate over a vector. To some extent this can be addressed by adding variants of `map` and `reduce` for these types, but these two operations would still be necessary.

> [@Karl](#):
>
> On the spelling issue, one of the big benefits of using a generic type would be type inference for the element type.

This is, AFAIK, the first concrete example of something that is actually simpler using the `Vector4<Float>` model that anyone has put forward, and is well worth consideration. Thank you.

---

<div class="post-metadata">

**Author:** ![scanon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/scanon/32/2445_2.png) [@scanon](https://forums.swift.org/u/scanon)\
**Post date:** [October 3, 2018, 2:05pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518/45 "2018-10-03T14:05:30Z")

</div>

> [@beccadax](#):
>
> **The `SIMD.Mask` types**
> 
> If I understand correctly, `VectorN<Bool>` can't really work for predicates/masks because the underlying representation of these is machine-dependent and isn't always compatible with a one-bit boolean. However, I don't understand why we can't model these as, say, `VectorN<VectorBool>` or something similar. I also have a sneaking suspicion (though I haven't tried it) that a good generic design could adjust for the fact that `Bool` looks different when it's inside a vector.

Because there isn't one `Vector4<VectorBool>` type. Comparisons on `Vector4<Int8>` (on x86\_64 or arm today) produce a mask where each lane is represented by eight bits. Comparisons on `Vector4<Float>` produce a mask where each lane is represented by thirty-two bits. It's vitally important for performance in SIMD code to keep lanewidth fixed as much as possible; you do not want to be going through narrowing / widening operations all over the place. We could collapse these types, but the optimizer today cannot eliminate all of the narrowing and widening operations that would entail, and long experience with the LLVM vector backend suggests that it would be folly to depend on that optimization.

---

<div class="post-metadata">

**Author:** ![scanon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/scanon/32/2445_2.png) [@scanon](https://forums.swift.org/u/scanon)\
**Post date:** [October 3, 2018, 2:10pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518/46 "2018-10-03T14:10:01Z")

</div>

> [@Chris\_Lattner3](#):
>
> It raises (for me) the question of whether would want to add language sugar to enable `v.0` like a tuple. If we did that, it could argue for `v.xy` and other niceties from other languages.

The biggest issue I see here is coming up with names that generalize to long vectors. `xyzw` works well for Vector4. `0123456789abcdef` gets us to `Vector16`. Beyond that, I'm stuck.

Generic tuple subscripting allowing extracting multiple members would be fun: `result.0112358d`, but in the meantime the `gathering:` init gives the same functionality in slightly more verbose form.

---

<div class="post-metadata">

**Author:** ![Tino](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/tino/32/1073_2.png) [@Tino](https://forums.swift.org/u/Tino)\
**Post date:** [October 3, 2018, 2:14pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518/47 "2018-10-03T14:14:38Z")

</div>

Imho this is one of many topics where a generous evaluation phase would make a lot of sense:  
I bet the discussion could go on for months, and the final result most likely would still have significant flaws.  
At the same time, there is an implementation that could be deployed right away, enabling people to gain hands-on experience...  
It would even be possible to include several spellings - I guess simply adding another implementation would take less time than arguing about its theoretical benefits.

---

<div class="post-metadata">

**Author:** ![beccadax](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/beccadax/32/34217_2.png) [@beccadax](https://forums.swift.org/u/beccadax)\
**Post date:** [October 3, 2018, 3:32pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518/48 "2018-10-03T15:32:31Z")

</div>

> [@scanon](#):
>
> I don't mind the extra boilerplate, but I think that we should encourage styles that minimize the boilerplate for users who copy the style of the standard library in their own code.

One of the standard library's jobs is to handle and hide the awkwardness of builtin types. This is why GYB and the Builtin module exist in the standard library but not elsewhere. Users need to be judicious about which parts of the standard library they copy.

In other words, we should favor an approach which makes the public interfaces as simple and clean as possible, rather than one which reduces boilerplate in the standard library but exposes the shape of the underlying implementation.

In other other words, `Vector3<Float>`, not `Float.Vector3`.

If we're worried users will take the wrong lessons from the standard library's design, we could have separate `VectorizableN` and `_BuiltinVectorizableN` protocols to separate the part users should emulate from the part they shouldn't:

```swift
// Protocol anyone can conform to in order to allow vector operations on a type.
// CGFloat could conform to this, for instance, and specify `Float`
// or `Double` for its `Vectorizable4Type` on a platform-specific basis.
public protocol Vectorizable4 {
  associatedtype VectorizableType: _BuiltinVectorizable4
  init(vectorizable: VectorizableType)
  var vectorizable: VectorizableType { get }
}
public protocol _BuiltinVectorizable4 {
  // Wrappers around primitive operations
}

```

> [@scanon](#):
>
> Because there isn't one `Vector4<VectorBool>` type. Comparisons on `Vector4<Int8>` (on x86\_64 or arm today) produce a mask where each lane is represented by eight bits. Comparisons on `Vector4<Float>` produce a mask where each lane is represented by thirty-two bits.

This is an excellent reason (and one I didn't have the background to understand on my own). Thanks for explaining.

Is there a reason why, for instance, `Vector4<Int32>` and `Vector4<Float>` should have the same mask type? I understand that they _can_ because they have the same bit width and lane width, but are there reasonable cases where you would want to compute the mask for a `Float` vector from an `Int32` vector or vice versa? If not, we might consider making each `VectorN<T>` have a distinct `VectorN<T>.Mask` type. That would prevent accidental mixing and further reduce the public interface by changing a typealias + several possible types to use for it into a concrete nested type.

---

<div class="post-metadata">

**Author:** ![scanon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/scanon/32/2445_2.png) [@scanon](https://forums.swift.org/u/scanon)\
**Post date:** [October 3, 2018, 4:00pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518/49 "2018-10-03T16:00:41Z")

</div>

> [@beccadax](#):
>
> Is there a reason why, for instance, `Vector4<Int32>` and `Vector4<Float>` should have the same mask type? I understand that they _can_ because they have the same bit width and lane width, but are there reasonable cases where you would want to compute the mask for a `Float` vector from an `Int32` vector or vice versa? If not, we might consider making each `VectorN<T>` have a distinct `VectorN<T>.Mask` type. That would prevent accidental mixing and further reduce the public interface by changing a typealias + several possible types to use for it into a concrete nested type.

I would say that cases where you want to intermix these are rare, but they do exist. You would be able to work around it via an explicit conversion, of course, which would compile down to a no-op.

I would be more or less fine with doing it either way; it would reduce the set of top-level types, but increase the total set of exposed types, and complicate the implementation of some of the functions on the float and integer types ever so slightly.

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [October 3, 2018, 6:03pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518/50 "2018-10-03T18:03:34Z")

</div>

> [@beccadax](#):
>
> Vectors are in some ways collection-like—they have several elements of identical type, they are subscriptable, they can be initialized from an array literal, etc. And yet they don't conform to `Collection` , apparently out of concern that users may accidentally write un-vectorized algorithms with that conformance.

The subscript is very useful (you can do stuff like selecting basis vectors with way fewer `if` statements) but I don’t think it means SIMD vectors are `Collection`-like or that it should be removed to ward off any suspicions. the array initializer should really be thought of as a way to initialize a vector from raw data,, maybe a `Array.load(at:)` method that returns a vector might be more appropriate.

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [October 3, 2018, 6:06pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518/51 "2018-10-03T18:06:31Z")

</div>

> [@00buggy00](#):
>
> Despite some talk on the discussion thread regarding keeping SIMD vectors apart from collections, there is still some awkward collection functionality remaining such as subscripting and `count` .

think of the `count` property as being analogous to the `bitWidth` property on scalar types. also keep in mind at one point we _were_ actually planning on adding subscripts to homogenous tuples so having a `[]` doesn’t mean `Collection`.

> If the previously mentioned naming convention were used, you wouldn't need a `count` method as you already known how many values are in the vector.

Saying you don’t need the `count` property because the length of the vector is in the name is like saying `Int32` doesn’t need the `bitWidth` property because the number of bits is in the name. it’s useful for generic programming.

> [@Karl](#):
>
> We have had much longer discussions about much smaller additions to the language.

is this a bug or a feature?

---

<div class="post-metadata">

**Author:** ![Karl](https://avatars.discourse-cdn.com/v4/letter/k/34f0e0/32.png) [@Karl](https://forums.swift.org/u/Karl)\
**Post date:** [October 3, 2018, 6:18pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518/52 "2018-10-03T18:18:36Z")

</div>

> [@taylorswift](#):
>
> is this a bug or a feature?

Hah, well I suppose it’s better to “measure twice, cut once”. There’s no rush; Swift 5 won’t be released for a while yet.

It’s a really good start (not taking anything away from it - I think steve has done a great job and obviously has vast expertise in this area), but I think it’s clear from the comments so far that the design as proposed is not ready to become part of the standard library. So that’s my answer to the actual _review_ part of this thread.

---

<div class="post-metadata">

**Author:** ![ben-cohen](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/ben-cohen/32/296_2.png) [@ben-cohen](https://forums.swift.org/u/ben-cohen)\
**Post date:** [October 3, 2018, 6:28pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518/53 "2018-10-03T18:28:09Z")

</div>

> [@Karl](#):
>
> There’s no rush; Swift 5 won’t be released for a while yet.

This is not really accurate. The final branch date for Swift 5 is only about [a month off](https://swift.org/blog/5-0-release-process/).

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [October 3, 2018, 6:33pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518/54 "2018-10-03T18:33:46Z")

</div>

> [@ben-cohen](#):
>
> > There’s no rush; Swift 5 won’t be released for a while yet.
> 
> This is not really accurate. The final branch date for Swift 5 is only about [a month off](https://swift.org/blog/5-0-release-process/).

and here we have an example of a procrastinator, and an anticipator

---

<div class="post-metadata">

**Author:** ![Chris\_Lattner3](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/chris_lattner3/32/348_2.png) [@Chris\_Lattner3](https://forums.swift.org/u/Chris_Lattner3)\
**Post date:** [October 3, 2018, 6:43pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518/55 "2018-10-03T18:43:33Z")

</div>

> [@Karl](#):
>
> On the spelling issue, one of the big benefits of using a generic type would be type inference for the element type. For example:
> 
> ```swift
> func doSomething(_ values: [Int32]) {
> let vec = Vector4(values) // Element type inferred from Array type - Vector4<Int32>.
> }
> 
> ```
> 
> Without generics, we would have to be explicit every time:
> 
> ```swift
> func doSomething(_ values: [Int32]) {
> let vec = Int32.Vector4(values) // Repetition of 'Int32'.
> }
> 
> ```

Great point.

---

<div class="post-metadata">

**Author:** ![Chris\_Lattner3](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/chris_lattner3/32/348_2.png) [@Chris\_Lattner3](https://forums.swift.org/u/Chris_Lattner3)\
**Post date:** [October 3, 2018, 6:48pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518/56 "2018-10-03T18:48:28Z")

</div>

> [@scanon](#):
>
> The biggest issue I see here is coming up with names that generalize to long vectors. `xyzw` works well for Vector4. `0123456789abcdef` gets us to `Vector16` . Beyond that, I'm stuck.
> 
> Generic tuple subscripting allowing extracting multiple members would be fun: `result.0112358d` , but in the meantime the `gathering:` init gives the same functionality in slightly more verbose form.

`.xyxy` syntax is _definitely_ useful for Vec2/3/4, perhaps useful for vec8. by the time I get to something like `vec.bc4e` I can't keep track of what is going on, so it serves no value. I don't think we "have to" support this for large vectors of 8 or more, and I see little value in doing so, so lets not!

What do you think? Have you found reasonable use cases for this syntax of vec8+ types in your code?

-Chris

---

<div class="post-metadata">

**Author:** ![Chris\_Lattner3](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/chris_lattner3/32/348_2.png) [@Chris\_Lattner3](https://forums.swift.org/u/Chris_Lattner3)\
**Post date:** [October 3, 2018, 6:51pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518/57 "2018-10-03T18:51:30Z")

</div>

> [@taylorswift](#):
>
> > Despite some talk on the discussion thread regarding keeping SIMD vectors apart from collections, there is still some awkward collection functionality remaining such as subscripting and `count` .
> 
> think of the `count` property as being analogous to the `bitWidth` property on scalar types. also keep in mind at one point we _were_ actually planning on adding subscripts to homogenous tuples so having a `[]` doesn’t mean `Collection` .

Just to probe on this a little bit - given that we don't want vectors to be used as collections, and given that `.count` on arithmetic types can be confusing, wouldn't it make more sense to name this property `.elementCount`?

-Chris

---

<div class="post-metadata">

**Author:** ![taylorswift](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/taylorswift/32/43413_2.png) [@taylorswift](https://forums.swift.org/u/taylorswift)\
**Post date:** [October 3, 2018, 6:55pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518/58 "2018-10-03T18:55:51Z")

</div>

> [@Chris\_Lattner3](#):
>
> Just to probe on this a little bit - given that we don't want vectors to be used as collections, and given that `.count` on arithmetic types can be confusing, wouldn't it make more sense to name this property `.elementCount` ?

probably, yeah

---

<div class="post-metadata">

**Author:** ![scanon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/scanon/32/2445_2.png) [@scanon](https://forums.swift.org/u/scanon)\
**Post date:** [October 3, 2018, 6:59pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518/59 "2018-10-03T18:59:39Z")

</div>

> [@Chris\_Lattner3](#):
>
> Just to probe on this a little bit - given that we don't want vectors to be used as collections, and given that `.count` on arithmetic types can be confusing, wouldn't it make more sense to name this property `.elementCount` ?

I would push back lightly on that and say that even though they aren't collections, when you are using `count`, you are using them in ways very similar to how you would use `Collection`; it's the established name in Swift for "the number of elements in a thing", and we should stick to that, rather than making up a new term for each domain. If we defined this number on Tuples (I don't see any reason to, but ...) I expect we would call it `count` as well.

---

<div class="post-metadata">

**Author:** ![00buggy00](https://avatars.discourse-cdn.com/v4/letter/0/cab0a1/32.png) [@00buggy00](https://forums.swift.org/u/00buggy00)\
**Post date:** [October 3, 2018, 7:01pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518/60 "2018-10-03T19:01:28Z")

</div>

> [@scanon](#):
>
> can you clarify what you mean by "Swift feel"?

When I look at `Float.Vector4` the first thing that comes to mind is a nested type and when I try to reason about what that means, I feel it is misleading and thus not very Swift. To me, when I see `Float`, I think that of a single value. Then when I look at that `Float`'s nested type, `Vector4` I see something is plural. Unlike `Array` or `Dictionary` where I expected a singular thing that holds many things, I do not think of a `Float`, as one number, not multiple numbers. `Vector4<Float>` reads in a more straightforward way, in my opinion, because I expect a vector to be one thing that is made of multiple values. A `Vector4` contains four values, and `<Float>` tells me that those values are each a `Float`.

> [@scanon](#):
>
> To me, `Vector4<Float>` vs `Float.Vector4` is basically "colour" vs "color".

To me, it is the difference between a "bushel of apples" and an "apple of bushels".

> [@scanon](#):
>
> `simd_float4` is not-very-swift, because it doesn't follow the conventions and doesn't enable generic code.

I completely agree with you.

> [@scanon](#):
>
> If you all feel really strongly about `Vector4<Float>` , I'm OK with that, but I hope that you'll push just as hard for the language features that would actually make that the natural spelling.

In the discussion thread, it was conceded that the presence of difficulty in using `Vector4<Float>` as the natural spelling was likely a sign of a language deficiency and one that should be amended. It would be better to get this truly working now then to look back later and say, "why didn't we do that", and "it's too messy to fix it now"--should we decide to go with `Vector4<Float>` which I personally hope that we do.

It would be great if you could go into greater detail on what the languages features would be that would be needed.

> [@scanon](#):
>
> In this case, the `count` property is still useful in both instances to enable writing code that is generic over vector length.

To both you and @taylorswift, I see what you're saying. I don't think thinking of `count` as like a `bitWidth` is quite the right way to put it though. My thinking was that `count` feels more synonymous with a collection of elements, but I absolutely see your point and agree with both of you.

> [@scanon](#):
>
> [...] these two operations would still be necessary.

That's fine, but again, there is much talk about not thinking about vectors as collections. I think this is another case where the proposal could use more clarity on what is being implemented and why.

---

<div class="post-metadata">

**Author:** ![00buggy00](https://avatars.discourse-cdn.com/v4/letter/0/cab0a1/32.png) [@00buggy00](https://forums.swift.org/u/00buggy00)\
**Post date:** [October 3, 2018, 7:25pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518/61 "2018-10-03T19:25:52Z")

</div>

> [@scanon](#):
>
> it's the established name in Swift for "the number of elements in a thing", and we should stick to that, rather than making up a new term for each domain. If we defined this number on Tuples (I don't see any reason to, but ...) I expect we would call it `count` as well.

That's a good point, but also seems to indicate that, despite no one wanting to think of vectors as collections, they still are when comes right down to it. Not that I am voting to provide them with all of the associated conformances though. Just an observation, haha.

---

<div class="post-metadata">

**Author:** ![scanon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/scanon/32/2445_2.png) [@scanon](https://forums.swift.org/u/scanon)\
**Post date:** [October 3, 2018, 8:13pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518/62 "2018-10-03T20:13:32Z")

</div>

We're getting off into the weeds here, but there's a lot more to `Collection` conformance than "contains a finite number of elements".

---

<div class="post-metadata">

**Author:** ![Jens](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jens/32/12903_2.png) [@Jens](https://forums.swift.org/u/Jens)\
**Post date:** [October 3, 2018, 8:19pm UTC](https://forums.swift.org/t/se-0229-simd-vectors/16518/63 "2018-10-03T20:19:25Z")

</div>

> [@taylorswift](#):
>
> think of the `count` property as being analogous to the `bitWidth` property on scalar types.

I just feel the need to point out that this analogy might be a bit misleading in that the number of elements multiplied by the number of bits per element is not always the number of bits used to represent a SIMD vector.

For example a (SIMD) vector of 4 and a (SIMD) vector of 3 `Floats` are both represented by `4 * 4 * 8 == 128` bits.

```
import simd

typealias ML3f = MemoryLayout<simd_float3>
typealias ML4f = MemoryLayout<simd_float4>
print(
    ML3f.size == ML4f.size &&
    ML3f.stride == ML4f.stride &&
    ML3f.alignment == ML4f.alignment
)
// prints true

```

[Previous page](https://forums.swift.org/t/se-0229-simd-vectors/16518.md?page=2)

[Next page](https://forums.swift.org/t/se-0229-simd-vectors/16518.md?page=4)
