tc39 / ecmascript_simd

SIMD numeric type for EcmaScript
Other
541 stars 64 forks source link

How orthogonal should operations be? #187

Closed littledan closed 9 years ago

littledan commented 9 years ago

At TC-39, someone (Mark Miller?) raised the question about why min/max is only on floating point types, when it could be defined on all types. The reason is because it can already be implemented in terms of lessThan and select for integers, though floats have more complexity.

I think the current operations provided by the polyfill are good in their relatively minimal state, but I'm opening this bug just to be a placeholder for people to express their opinions and so we keep track of what was brought up there. A policy of having operations only for where we think they will be accelerated by hardware and not implementable in terms of other operations is a good one.

Keep in mind, however, that in "spec land", leaving out these operations makes the spec longer and more complicated. A simple spec is desirable by TC-39. The argument could be made that the lack of orthogonality makes it harder for people to start learning how to use SIMD.

However, I think minimalism overrides that.

johnmccutchan commented 9 years ago

As an aside, writing efficient SIMD programs is hard and what makes that job hard is structuring your data so that you can use SIMD operations on them in the first place. Grokking the SIMD API is probably the least of a developers worries.

littledan commented 9 years ago

Agree that people have to really understand SIMD to use it, and I'm not proposing any spec changes. However, in general, I think we should take our spec audience seriously. We are currently proposing this for the main Javascript spec that all Javascript implementations are supposed to implement forever. Given the lifetime of Javascript so far and the hardware changes that have happened over the last 20 years, that's a big deal. But I agree that we should actually keep the API minimal in the sense of not including int min and max.

littledan commented 9 years ago

We discussed this in the call today, and decided that minimalism is the more important concern. No changes are needed.

ljharb commented 9 years ago

I think consistency is pretty important, and makes it much easier to teach and learn this aspect of the spec.

If the common operations were grouped using inheritance, then for example, all integer types could inherit from %SIMDIntegerPrototype% which means that https://github.com/johnmccutchan/ecmascript_simd/issues/205#issuecomment-112938479 wouldn't apply, the spec would be even shorter than it is now, and Mark's (and my) concern would be satisfied as well.

I think that any method that exists on any SIMD type, that makes sense on other SIMD types, should be there, even if we can't foresee a need to optimize them yet.

I also immediately have a use case for int min/max - Twitter tweet IDs are 64-bit integers, and I've needed to compare them since they're used as cursor values for pagination. This polyfilled operation would be much better than using strings, and having to use a special string-to-integer library to compare them.

littledan commented 9 years ago

Let's work on 64-bit integers separately. I'm interested in them, but I don't think SIMD values are the right way to store them.

I'm not sure what you mean by 'inherit'. There's no prototype chain relationship between either the SIMD values (as they are primitives) or the wrapper constructors or the wrapper prototypes. Do you think there should be? The only relationship is this spec-land SIMD meta-variable to range over the SIMD types.

SIMD is meant to be an API that fits within Javascript conventions generally, but used as an advanced performance feature by people who want to spend time learning about it. IMO minimalism beats orthogonality here; each individual function we add is a burden to understand its individual performance properties. A user library can always add min and max functions for ints based on the existing primitives, and they could be added in a later standardization round, but not removed.

ljharb commented 9 years ago

They are primitives, but all the methods on them are from autoboxing to a prototype chain, just like Number and other primitives. Thus, you absolutely could have a superclass that the primitive wrappers inherit from, and it would work fine, and simplify both the spec and the implementation.

This was going to be a problem with iterators in ES6, and was fixed by adding %IteratorPrototype% which is a common superclass for all their common behavior.

littledan commented 9 years ago

Sure, we could do that, but what's the benefit? We couldn't define .add() and similar methods on the prototype that way since asm.js would have trouble inferring types.

ljharb commented 9 years ago

Why would asm.js be able to infer the type from an own property function, but not from an inherited property function? Both have the same access to this, and especially if they're primitives, no inference is needed, since this would have an internal slot.

littledan commented 9 years ago

Because no property functions are involved, and there is no this. There are just function properties of the Float32x4 object, like the Math functions.

ljharb commented 9 years ago

Ah, I see - and they're meant to be callable when detached from the type too? If so, then you're right, any organization would solely be in the spec, and not in any implementations, so it might not be worth it. However, if not, then by being called off the Float32x4 object means that that would be the "this", and such organization would be possible.

littledan commented 9 years ago

Even if we made them refer to this, they would be basically a switch statement to figure out which function to call, so that wouldn't really be a good idea. But also, from the point of view of asm minimization, it's useful to be able to pull them off.