This forum has been archived. All content is frozen. Please use KDE Discuss instead.

[SOLVED] Can custom types be vectorized?

Tags: None
(comma "," separated)
Ian Mackenzie
Registered Member
Posts
15
Karma
0
I'm using a custom type

typedef Eigen::Matrix Vector3I;

where Interval is a typedef for a Boost interval type having two double values as members. As a result, the size of a Vector3I is 3 * 2 * 8 = 48 bytes, so it counts as 'fixed size vectorizable'...but does that actually make sense? Even though a Vector3I is a multiple of 16 bytes, can it actually be vectorized? I figured that could only be done for known types like floats and doubles.

It's not a big deal for me to put the EIGEN_ALIGNED_OPERATOR_NEW macro in my classes which have Vector3I members, but I'm curious to know whether operations on Eigen objects based on custom types can actually be vectorized correctly...
User avatar
bjacob
Registered Member
Posts
658
Karma
3
It depends on the custom scalar type. In your case, since your scalar type is 2 double's, that's 16 bytes which is exactly the size of a SSE/AltiVec packet. This means that 1 packet would be 1 Interval. In order to vectorize, Eigen would need you to provide functions like ei_padd, ei_pmul... computing the sum, the product... of 2 packets; now since a packet is exactly an Interval, this means that you need to vectorize the basic arithmetic operations on Interval's. This seems to be doable (i mean potentially worth it).

So the first step is to have a look at arch/SSE/PacketMath.h, you need to specialize ei_packet_traits for your type, and define the ei_p...() functions.

About having to put the EIGEN_ALIGNED_OPERATOR_NEW macro, that's a good point, I agree that's annoying, but it's very hard to do otherwise while preserving the ABI if we want to vectorize more numeric types in the future.


Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list!
Ian Mackenzie
Registered Member
Posts
15
Karma
0
Cool - I didn't know about ei_packet_traits and the ei_padd etc. functions, and it definitely sounds like those are worth checking out. I've already specialized NumTraits, of course, and defined all the ei_add etc. functions - anything else I should be looking at trying to specialize?

I really don't mind the EIGEN_ALIGNED_OPERATOR_NEW macro - I'm sure it was the best possible solution, and I don't think I was in much danger of wanting to define my own operator new() anyways.
User avatar
bjacob
Registered Member
Posts
658
Karma
3
Ian Mackenzie wrote:Cool - I didn't know about ei_packet_traits and the ei_padd etc. functions, and it definitely sounds like those are worth checking out. I've already specialized NumTraits, of course, and defined all the ei_add etc. functions - anything else I should be looking at trying to specialize?


(You mean ei_padd not ei_add). Look in that file arch/SSE/PacketMath.h. I think there's also a struct ei_unpacket_traits. And you need to define not only the "interesting" functions ei_padd, ei_pmul... but also all the "boring" ones: ei_pload, ei_pstore... that should be it.

Ian Mackenzie wrote:I really don't mind the EIGEN_ALIGNED_OPERATOR_NEW macro - I'm sure it was the best possible solution, and I don't think I was in much danger of wanting to define my own operator new() anyways.


Oh but you could have your custom operator new(): all what we require is that it returns 16-byte-aligned pointers. EIGEN_ALIGNED_OPERATOR_NEW just makes a basic such operator new but you can have your own instead.


Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list!
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
if you only want to support double, then it is much simpler: since in your case PacketType == ScalarType == Interval, simply use an Eigen Vector2d in your Interval class for storage, and use Vector2d operators... the later will be automatically vectorized by eigen. No need to reimplement ei_p* function ! For more tricky function like the product, you might reuse the ei_p* function to implement the vectorized version.

Now, if you also want to support float then you have to consider the cases where PacketType == multiple Intervals and implement specialized versions of the ei_p* functions.
Ian Mackenzie
Registered Member
Posts
15
Karma
0
Wow, replies from not one but two lead developers on the same day - pretty awesome!

bjacob wrote:(You mean ei_padd not ei_add). Look in that file arch/SSE/PacketMath.h. I think there's also a struct ei_unpacket_traits. And you need to define not only the "interesting" functions ei_padd, ei_pmul... but also all the "boring" ones: ei_pload, ei_pstore... that should be it.


Sorry for the confusion - I just meant that a long time ago I did the simple specialization of NumTraits and the 'normal' ei_add etc. functions so that the Interval class would work at all (as described on the 'Customizing/Extending Eigen' page), and I was wondering if in addition to the packet math structs and functions there was anything other interesting structs and functions to specialize...for instance, if I wanted to add a Vector3d to a Vector3I I could currently do something like

Code: Select all
Vector3I a(Interval(1, 2), Interval(2, 3), Interval(4,5));
Vector3d b(1, 2, 3);
a += b.cast();


but it would be nicer to do

Code: Select all
Vector3I a(Interval(1, 2), Interval(2, 3), Interval(4,5));
Vector3d b(1, 2, 3);
a += b;


because there is a direct function to add a double to an interval (simply adding it to both member doubles) without converting the double to a second interval first. I thought perhaps there were some structs and functions that I could specialize that described how Interval objects interacted with doubles or something...

bjacob wrote:Oh but you could have your custom operator new(): all what we require is that it returns 16-byte-aligned pointers. EIGEN_ALIGNED_OPERATOR_NEW just makes a basic such operator new but you can have your own instead.


Yeah, I figured as much - I really just meant that if I had wanted to define my own operator new() it might have been a hassle to do so, but that's not a concern.

I'll look at the the represent-interval-as-Vector2d thing...thinking out loud here, could you pull some sort of trickery with Map classes to map an interval object to a Vector2d for certain operations?
User avatar
bjacob
Registered Member
Posts
658
Karma
3
I agree with Gael, if you have the freedom to reimplement Interval, then by just implementing it on top of Vector2d you'd get vectorization for free!

Regardless,

Ian Mackenzie wrote:
Code: Select all
Vector3I a(Interval(1, 2), Interval(2, 3), Interval(4,5));
Vector3d b(1, 2, 3);
a += b.cast();


but it would be nicer to do

Code: Select all
Vector3I a(Interval(1, 2), Interval(2, 3), Interval(4,5));
Vector3d b(1, 2, 3);
a += b;



This is something that you can fix by writing a MatrixBase plugin:
http://eigen.tuxfamily.org/api/CustomizingEigen.html


Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list!
Ian Mackenzie
Registered Member
Posts
15
Karma
0
bjacob wrote:I agree with Gael, if you have the freedom to reimplement Interval, then by just implementing it on top of Vector2d you'd get vectorization for free!


Yes, I think I'll try that - thanks to both of you for all your help!


Bookmarks



Who is online

Registered users: Bing [Bot], Google [Bot], Sogou [Bot]