Skip to main content
gamedev.net
🔒 Locked

Parallel multiplication

Started by Lode Feb 20, 2005 at 10:44 AM 8 replies 1k views
Original Post
Lode
Lode
I have 2 32-bit integers c and m. Each 32-bit integer contains 3 bytes at positions 00FF0000, 0000FF00 and 000000FF (so the first byte of the 32-bit integer contains no data). I want to multiply each byte of c with the corresponding byte of m, and store that into the 32-bit integer f. I want to do this in one line of C++ code, and in the way with the fewest operations possible. I can't get it any smaller than this though:

f = (((((c & 0xFF0000) >> 16) * ((m & 0xFF0000) >> 16)) >> 8) << 16) | ((((c & 0x00FF00) * (m & 0x00FF00)) >> 24) << 8) | (((c & 0x0000FF) * (m & 0x0000FF)) >> 8);
Can you get it smaller and more efficient?
Trap
Trap
You use your int as a byte[4] vector and want a dot-product for the special case of byte[0]==0?
twix
twix
Is there a reason you'd do something so inherently inefficient in the first place, or is this just for fun? [grin]
Lode
Lode
Quote:
Original post by Trap
You use your int as a byte[4] vector and want a dot-product for the special case of byte[0]==0?


No it's not a vector it's an RGB color (with the alpha channel being ignored), and it's not the dot product but a component-wise product.

And it's for fun! (I came up with it while coding tho and might still use it ;))
marcusz
marcusz
When you're doing this kind of optimization you need to know the hardware. Can it shift fast? Fast multiplications or should you use tables? Memory bandwidth limited? If you miss the level1-3 caches the CPU may stall for hundreds of clock cycles and _this_ is the bottleneck - not processing the pixels/colors.

The _optimizations_ are often not portable - keep the original, clean code for the future!


You can do this with two multiplications instead of three :-P

Also, you don't need to shift all color components around this much. Draw each of the color components as bit-ranges on a piece of paper _separately_ and figure-out the optimal set of logical operations for each component.

Another thing you can think about: right now there are a lot of dependencies between the different operations that can cause CPU stalls. Try interleaving other stuff in between - possible interleave the same code but processing another color (pixel?) at the same time. Depending on HW, the second pixel might be "free" CPU-wize = 200% faster.

Yet another thing: if this code is the biggest bottleneck, can you preprocess your data to make this code snippet do less work?


HTH


/Marcus
matt_j
matt_j
Doesn't MMX do something fancy like this?
superpig
superpig
Yes, but it depends on how you want to handle overflows.
Richard "Superpig" Fine - saving pigs from untimely fates - Microsoft DirectX MVP 2006/2007/2008/2009
"Shaders are not meant to do everything. Of course you can try to use it for everything, but it's like playing football using cabbage." - MickeyMouse
Trap
Trap
Why don't you just load every part as an unsigned char, multiply them and store again? Maybe by using a union of 1 int and 4 unsigned chars.
Lode
Lode
Quote:
Original post by Trap
Why don't you just load every part as an unsigned char, multiply them and store again? Maybe by using a union of 1 int and 4 unsigned chars.


That's not one line of code. I'm looking for something that looks "cool", not necessarily readable, like that way to swap two variables in one statement ;)
Nemesis2k2
Nemesis2k2
I profiled that single line variable swap once. It was something like 4 times slower. You ended up with the same number of mov instructions, it just did an XOR between everything.

//Using temporary	int temp = two;00411A2C  mov         eax,dword ptr [two]00411A2F  mov         dword ptr [temp],eax 	two = one;00411A32  mov         eax,dword ptr [one] 00411A35  mov         dword ptr [two],eax 	one = temp;00411A38  mov         eax,dword ptr [temp] 00411A3B  mov         dword ptr [one],eax //Using XOR	one ^= two ^= one ^= two;00411A3E  mov         eax,dword ptr [one] 00411A41  xor         eax,dword ptr [two] 00411A44  mov         dword ptr [one],eax 00411A47  mov         ecx,dword ptr [two] 00411A4A  xor         ecx,dword ptr [one] 00411A4D  mov         dword ptr [two],ecx 00411A50  mov         edx,dword ptr [one] 00411A53  xor         edx,dword ptr [two] 00411A56  mov         dword ptr [one],edx 


Keep it simple.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.