SynthMaker

Real uses for shufps!

Archive · 2010 44 old posts

From the original SynthMaker forum (2004–2014), with its members’ names and dates.

trogluddite ·

Hi All, A little osm here with some handy little modules I knocked up using shufps. They're designed for schematics that use packed momo4 channels to run multiples of the same thing for lowering CPU.

Got the CPU on my latest project down by a quarter using these, and the one for selecting a mono stream from a mono4 prevents the hassle of SM rewiring itself if you try to use selectors. The slow (hopped) unpack can be really handy for lowering CPU if you find yourself having to do lots of unpacking just to peek at streams for displays etc.

So, shufps is useful after all - never thought I'd say that. 😉

The Luddite

Acrobat ·

Hi, Trog, thanks fof those, I guess the "Add Streams" is slow too, right?

MichaelBenjamin ·

the get mono imo uses a lot of code for that task, i made up another version, with 1 mul and 3 add and 2 pack primitives. i dont know how much the packs use but it cant be that much.

MichaelBenjamin ·

ah i just measured in white, seems yours is really a bit better since it doesnt need the pack and the shufps seems really light on cpu. without the pack it measures roughly the same. plus, your version can be modulated in realtime, so forget mine. good job.

exonerate ·

Excellent!

Thanks for these really useful 🙂

Cheers 😉

Exo

sunsynth ·

Great Luddite... 😉

Have 2 add a new Group under ur name now... 😉

Cheers, SUNsynth

MegaHurtz ·

In theory.. isn`t it possible to use a bitshift on the shufps.

MyCo ·

MichaelBenjamin wrote: the get mono imo uses a lot of code for that task, i made up another version, with 1 mul and 3 add and 2 pack primitives. i dont know how much the packs use but it cant be that much.

ehm... why are you doing it so difficult?

MichaelBenjamin ·

probably rhetorical, but the answer is because i am stupid. can anybody tell me why i cant see the pictures in this forum? i only see a not clickable "getmono.jpg" checked the board prefs, image display is on, everything else works.

MegaHurtz ·

lol.

trogluddite ·

MyCo wrote: ehm... why are you doing it so difficult?

Selectors were wreaking havoc on my schematic because of the way they were causing a jump to stage(0). Posted here... Un-Natural Selection (BEWARE!) This method completely avoids the re-threads. Also I wanted something that I could hop - my schematic was using lots of unpacks at sample rate and they were seriously eating into the CPU.

Acrobat wrote: the "Add Streams" is slow too, right?

Add streams is at sample rate at the moment - but you can make it slow by adding the hopping part of the code. Just copy and paste the 1st few code lines up to 'jnz end0;' and the 'end0:' at the end of the slow unpack into the assembly primitive.

MegaHurtz wrote: In theory.. isn`t it possible to use a bitshift on the shufps.

Not so good on theory - so I'll just have to wade in with good old trial and error! 😈

sunsynth wrote: Have 2 add a new Group under ur name now...

The pleasure is all mine 🙂

mwvdlee ·

So what exactly does shufps do anyway? And why is it any faster than without?

exonerate ·

Here is another useful bit of code for the pack4.

It's for when you want to have a different static variable for each channel.

streamout out; //Declare static variables float tmp1 = 45; float tmp2 = 32; float tmp3 = 23; float tmp4 = 11;

stage0; mov eax,tmp1[0]; mov out[0],eax;

mov eax,tmp2[0]; mov out[1],eax;

mov eax,tmp3[0]; mov out[2],eax;

mov eax,tmp4[0]; mov out[3],eax; stage0;

You just have to change the tmp variables to what ever value you like. I didn't add the variables as inputs because this adds overhead.

**edit**For an idea of where this code could be useful check the reverb that comes with SM 😉

It doesn't reduce the CPU use by that much "but every little helps".

Cheers 😉

Exo

Tzarls ·

Wouldn´t it be just like packing 4 floats?

exonerate ·

Tzarls wrote: Wouldn´t it be just like packing 4 floats?

Yes but this is faster than using the pack4 primitive.

Cheers 😉

Exo

trogluddite ·

mwvdlee wrote: So what exactly does shufps do anyway

shufps is an assembly opcode (not explained in the SM documentation) that lets you swap the four packed SSE channels around - if you do a forum search there are a few threads with links to full explanations - it is a bit of a mind bender of an instruction. It's very fast too, and can save you needing to unpack things when you don't want to affect all four streams. My main reason for writing these was because of an obscure problem I was having with selectors - see Un-Natural Selection (BEWARE!) It also has the advantage that, being an assembly command, you can use hopping to save CPU - my surrent project had several dozen unpack primitives being converted to green at only 50Hz, and changing them all for my hopped version saved a good few CPU cycles. So in this case, the CPU savings are from lowering the sample rate rather than any super-efficient coding on my part. Could be that some of these savings are specific to my schematic being a bit strange (and a bit large!) - I doubt they'd be useful very often. Just working on optimising these modules at the moment - quite a few CPU cycles still to save yet - I'll get them posted up when I've finished testing.

exonerate wrote: **edit**For an idea of where this code could be useful check the reverb that comes with SM

Interesting example - I'll post up my version of the reverb soon, I'm just working on using shufps to code that weird shuffling feedback path in the all pass filters. Tried to make a hopped version of the pack to go with the unpack - oddly enough, even hopped by 512, it was still no more efficient, so I guess packing is much more efficient than unpacking.

Tzarls ·

exonerate wrote: Tzarls wrote: Wouldn´t it be just like packing 4 floats?

Yes but this is faster than using the pack4 primitive.

Cheers 😉

Exo

Aha! I see now that you are doing the assignment inside stage 0, which means that the code is executed only once when it is initialized, right?

exonerate ·

Tzarls wrote: exonerate wrote: Tzarls wrote: Wouldn´t it be just like packing 4 floats?

Yes but this is faster than using the pack4 primitive.

Cheers 😉

Exo

Aha! I see now that you are doing the assignment inside stage 0, which means that the code is executed only once when it is initialized, right?

Yep that's right.

trogluddite ·

Here's the updated versions of those modules - all using lower CPU, particularly the Get Mono and Add Streams modules. Also included my first go at optimising the built in reverb using assembly - thanks to exo for the little stage(0) trick earlier in this thread 🙂 - shufps worked rather nicely on the feedback loop - but I'm sure there's plenty of CPU cycles to be saved yet.

exonerate ·

Nice one 🙂 that's some good optimizing.

I think the biggest reduction now with the reverb would come from putting everything in one asm block, this will enable some more optimizations and cut down on memory accesses. I big job though and could get messy 🙂

Cheers 😉

Exo

trogluddite ·

Glad you like it. Had to scrap my first go at an 'all in one' design - got myself very confused trying to get the stages right! I'll keep working on it - it's one of the biggest CPU hogs in my project at the moment.

DigitalWhiteByte ·

thanks Luddite, I will take inspiration from this work to study a little deeper ASM 🙂

oddson ·

I think the massive work towards a better reverb for SynthMaker users is getting lost in this thread with it's esoteric title. (If there's an opcode in the name I generally don't even read it.)

But it seems you've transfered some of the weaknesses of the Freeverb port into your own.

Big among them is that it's not sample-rate independent. The arbitrary delay lengths have been transfered into the assembly code where there's even less obvious then they were in Shif's version.

Also some of the rigid scaling decisions have been similarly hard-coded.

Before anyone spends too much time with consolidating them into a single block (and does that really save that much CPU?) I'd like to see some effort spent, perhaps as a group project, to make a really decent reverb with as much flexibility as possible (losing the idea that it's still a Freeverb 'port') but retaining the basic comb-allpass design. If the ASM crowd then want to make hard-code rate dependant versions to trim the last few CPU cycles possible then more power to them... but I think the community needs a better reverb to drop into their projects but where greater flexibility is retained.

trogluddite ·

A better and more flexible reverb is certainly a good idea - removing some of the sample rate limitations would certainly be a good start - never occured to me, as I never use anything but 44.1.. My intention was never to develop the reverb per se - it was more an exercise for myself in learning some better assembly optimising techiniques, and I happened to be using this module in something I'd been working on. To be honest, I may have a few code optimising tricks up my sleeve, but my understanding of the algorithms themselves is way short of improving the way this thing works. I'll rough out something sample rate independent and bump it over to a new project thread if I get a chance.

oddson ·

trogluddite wrote: I'll rough out something sample rate independent and bump it over to a new project thread if I get a chance.

I wasn't suggesting you be the one to do all the work... just that you've got a good start to it here and we should capitalize on it.

Do you mind if I post a thread with your module as a starting point and some analysis on what I think the project should include?

EDIT - on second thought I think I'll leave this for now... as soon as I started thinking about it i remembered all the problems that stopped me last time I tried for a flexible reverb.

trogluddite ·

oddson wrote: Do you mind if I post a thread with your module as a starting point and some analysis on what I think the project should include?

I've no problem with that - may be worth doing to see what anybody else might make of it.

matti ·

You can find the same shufps trick from my FIR convolution example 🙂

mwvdlee ·

I found another use for the shufps command!

Here's the problem: At the output stage of my schematic, I need to do... 1) Display some nice level bars 2) Mix in a metronome with the audio for output, but do not display metronome sound in the level bars 3) Clip everything to [-1,1]

Before the metronome I used a standard clipper with Mono4 in and out:

streamin In; streamout Out;

float F1=1; float FM1=-1;

movaps xmm0,In; minps xmm0,F1; maxps xmm0,FM1; movaps Out,xmm0;

Since I used only the first two channels of the Mono4, I found I could use the first 2 output channels of the Mono4 for audio and the last 2 for the level bar and mix in the metronome before clipping all channels in one go. To do this, I used shufps:

streamin In; streamin Aux; streamout Out;

float F1=1; float FM1=-1;

movaps xmm0,In; shufps xmm0,xmm0,17; // unpcklps addps xmm0,Aux; minps xmm0,F1; maxps xmm0,FM1; movaps Out,xmm0;

So there you go... another use of shufps.

If we had unpcklps, I wouldn't have needed shufps since a mask of "17" is effectively the same as unpcklps 😉

trogluddite ·

Nice One. Here's my favourite ATM to make sharing dezippers easier when controls need to be used by multiple channels - getting some good savings in bigger schematics...

...the top chain shows the usual way to distribute the control values if they are needed by multiple sse channels. The bottom way keeps it all in mono4, and redistributes the channels within the code using...

shufps xmmX,xmmX,0 - move sse[0] to all four channels shufps xmmX,xmmX,85 - move sse[1] to all four channels shufps xmmX,xmmX,170 - move sse[2[ to all four channels shufps xmmX,xmmX,255 - move sse[3] to all four channels

Kinda tidies the schematic too - using the mono4 like a bus for several controls.

mwvdlee ·

I made a big blunder in my previous code example. The value shouldn't be 17 (00010001b), but 68 (01000100b) ofcourse. 17 does copy the channels, but it also flips left/right channels. 68 just makes a plain copy of 0+1 to 2+3 without.

streamin In; streamin Aux; streamout Out;

float F1=1; float FM1=-1;

movaps xmm0,In; shufps xmm0,xmm0,68; // unpcklps addps xmm0,Aux; minps xmm0,F1; maxps xmm0,FM1; movaps Out,xmm0;

stw ·

Since it caused too much headache recalculating every shufps operand after i understood how it works i made this little helper for finding the right operands on the fly. I guess some of you already have a similar helper but i couldn't find one on the forum. Maybe it's helpful for others too. So here's a small shufps calculator.

EDIT: New version 1.3

stw ·

I upped a new version which beside creating an operand allows to set it. The result is shown in the matrix. That may be useful if a shufps comes around and you want to know which routing it creates. A hex value is diplayed too.

Mo ·

-Nice one, stw!

trogluddite ·

Thanks stw - that will save me a lot of mucking around in binary with Windows calculator!

MichaelBenjamin ·

very good, finally i maybe can use this.

aliasant ·

MichaelBenjamin wrote: very good, finally i maybe can use this.

+1

Brilliant tool. thank you!

mwvdlee ·

Convenient, simple... love it! Perhaps we should have a toolbox of such "helper" tools.

infuzion ·

Thanks stw; I was thinking of making my own & you saved alot of time. I do need to combine 2 different streams though, so I had to edit yours to help me figure out the 2. Also, the official docs start counting at 0.

stw ·

infuzion wrote: I do need to combine 2 different streams though, so I had to edit yours to help me figure out the 2. Also, the official docs start counting at 0.

You're right. Considering the asm code the counting should start at [0]. Since i'm a programmer dumbhead 😀 i do things like they appear in the "real world". For that reason channel 1-4 like in the pack/unpack modules was a bit more self explaining to me. And i didn't consider that 2 streams can be shuffled. Thanks for that hint. So i did a new version which hopefully takes care of these circumstances. I changed the GUI a bit so that one can choose between one or two inputs(operands). Routing can be changed by clicking on the out values. More clicks but visually clearer. Now you can also type into the HEX result box which calculates the routing like the INT box did before. I also changed the naming of mask/operand because i've mistaken the declaration before. The operands obviously are the registers itself while the created value is the mask. The former version also had a redraw issue which should be eliminated now...

infuzion ·

stw wrote: ...So here's a small shufps calculator. EDIT: New version 1.3

new edits by infuzion: by spec count 0-3 channels (In a binary world #1 is second place) copy/past full ASM command added presets fixed loopback issue after Int entry bugs: Hex display will not update properly, so I disconnected their Views, but the code is still there.

trogluddite ·

Excellent - the cut/paste box and presets are inspired; ultra quick access to those dozen or so really useful values.

infuzion ·

trogluddite wrote: Excellent - the cut/paste box and presets are inspired; ultra quick access to those dozen or so really useful values.

Thanks! Only a few presets so far; people can export a preset text file & upload just that if they add some more.

stw ·

Useful additions Infuzion. For the sake of completeness, here the "HEX fixed" version.

infuzion ·

stw wrote: Useful additions Infuzion. For the sake of completeness, here the "HEX fixed" version.

Thanks!

Wrote something here? To have a post removed or your name hidden, write to [email protected].

Before your first post

A few rules keep this a friendly place. You agree to them once.

Shown next to what you post, here and in the app. It doesn’t have to be your real name: 3–24 lower-case letters, digits or _ (capitals become lower case, spaces become _).

    Then your post goes up straight away.

    Delete this reply?

    Open it in SynthMaker?

    It goes on the track you’re editing there, in place of that track’s sound, and into My sounds. Your other tracks stay as they are.

    Want to keep that track’s sound? Start a new song in SynthMaker first (Song › New song), then open this.

    Report this reply?

    Only the developer reads reports. The person isn’t told who reported them.

    What’s wrong with it?

    Block this person?

    You won’t see their posts and replies here any more. They aren’t told, and you can unblock them at any time.

    People you’ve blocked

    Their posts and replies are hidden from you. Unblock someone to see them again.

    The community rules

    A few rules keep this a friendly place. Everyone agrees to them once, before their first post.