Non-enabled instruments consuming CPU?

Hey all

So I’m trying to figure out where the consumption of CPU is coming from in a program I am writing. On initializing csound I have many instruments, but none are called in the score and must be called by an external score event which will enable an instance of that instrument. Even when I don’t enable any of these instruments directly I am still getting a fairly large amount of CPU consumption. I noticed that if I eliminate half of the instruments from the .CSD file it yields about 50% reduction in CPU consumption so I’m assuming this is the culprit and somehow based on how csounds operates the instruments, while not activated, must still be executing some of their code as I can’t imagine the idle “waiting for event/activation” state itself would consume that much CPU on its own (I’m seeing about a 1-2% increase per instrument varying by its complexity)

My question is, do instruments that are not enabled still consume CPU each cycle and if so is there a way to limit/eliminate this consumption until they are enabled? I would think that after initialization they’d lie in a dormant state but maybe certain k/a-rate operations still execute even when no instances are currently present?

For context I am building a modular system so I anticipate a large amount of instruments but not necessarily a large amount of instruments to be enabled. Any insights appreciated

EDIT: I see a (sort of) similar question asked here: One or many instruments? - Csound Noobs - Cabbage Audio Forum but I’m not sure if the context is the same or if code within an instrument still executes even when no instances have been enabled directly (as I’m enabling instruments with fractional numbers). It looks like this was more of a “which would consume more/less CPU” than actually wondering if an instrument consumes CPU when no instances have been enabled

IMPORTANT NOTE: If non-enabled instruments should not be consuming CPU then it may be due to the fact that I am running this within Unity using the Csound Unity project. However I don’t see anything in the .cs files from Csound Unity that seem like it would be attempting to fetch audio from channels each fixed update (initially my thought was maybe somewhere it was checking every audio rate channel which was set but I don’t believe this is the case) so I’m guessing this is an unlikely source of the issue (but figured I’d throw it out there in case it is a possibility as I’m still getting familiar with that particular project’s source and have lots of holes in my understanding of its operation)

The first thing I would do is conduct this experiment using only Csound, and no frontends. If it doesn’t exhibit the same issues, then it clear the problem is with the frontend.

I have little knowledge of this, and could be talking total waffle here, but I believe each instrument gets compiled and added to the DAG. In Csound parlance this is referred to as a TREE. I don’t know how Csound behaves if the instruments in the TREE aren’t performing. @stevenyi, seems like you’re the only Csound dev who made it to the forum? Can you enlighten us?

Okay so I executed two .CSD files from the command line. The first being the blank .CSD file and the second being my file with the instruments declared but nothing is initialized in the score section. I found that both seem to consume the same amount of CPU resources (assuming the Win10 Resource Monitor is a reliable tool for monitoring the CPU consumption) so I believe this may indicate that the DSP CPU Consumption could have something to do with the Csound Unity implementation

My hunch, and I may be incorrect, but I believe this may have something to do with this section in the CsoundUnity.cs file:

                        if ((ksmpsIndex >= GetKsmps()) && (GetKsmps() > 0))
                        {
                            var res = PerformKsmps();
                            performanceFinished = res == 1;
                            ksmpsIndex = 0;

                            foreach (var chanName in availableAudioChannels)
                            {
                                if (!namedAudioChannelTempBufferDict.ContainsKey(chanName)) continue;
                                namedAudioChannelTempBufferDict[chanName] = GetAudioChannel(chanName);
                            }
                        }

I think that availableAudioChannels is populated by parsing the .CSD file, which I would assume would fetch any and all a-rate channel set/get methods within the csd, so this may be fetching data for channels it found each cycle? Again I’m not positive but it’s just a hunch

EDIT: So it appears that section actually only has 2 audio channels so I doubt that’s the source of the issue

I think that should only populate with channels for a child component. @g_b can answer better than I. But I think you are right in assuming that it’s a red herring.

I can’t think what might be going on that would cause this spike in the CPU.

I’ll do a bit more testing today and see if I can further isolate the problem. If I manage to locate the source I’ll file an issue on the github. Thanks for getting back

Okay so after doing a bit more digging, I found that it is definitely relating to channel setting/getting. Considering I saw basically no CPU difference between my empty .CSD and my .CSD with uninitialized instruments when run from the command line it definitely seems correlated to how Csound Unity is handling channel getting/setting somewhere. I found that in particular, this opcode which I wrote to set channels causes the DSP CPU usage to double:

;sets all channels to a single a-var starting at index 1
opcode setconnchnls,0,aS[]p
  aVal, Schnls[], iCnt xin
  if(lenarray:i(Schnls) > 1) then
	  chnset aVal, Schnls[iCnt]
	  if iCnt < lenarray:i(Schnls)-1 then
	   setconnchnls aVal, Schnls, iCnt+1
	  endif
  endif
endop

With the opcode existing as is (not being actually called mind you, as none of the instruments that call it are initialized so none of their code should actually be calling it) the DSP CPU usage in Unity sits at around 10%, once I removed this opcode it reduced the CPU Usage to about 4.7%. I noticed that as I removed more and more calls to chnget, chnset, etc the DSP CPU Usage dipped more and more until it eventually returned to expected baseline levels.

I believe that the Csound Unity project must be doing something with these channels potentially as when run via command line I’m not seeing such issues so I assume it must be originating somewhere in the .cs code. Any direction as to where to look in the source would be greatly appreciated, I’m willing to try my hand at resolving this and submitting a PR if I can find a solution that reduces the usage while preserving the existing functionality.

@g_b If you wind up wanting to take a look let me know and I’ll email you some the test .CSD files I have. I named each of them pretty explicitly so the changes are obvious as to what is removed so you can easily see how modification of the original .CSD correlates to reduction in DSP CPU consumption

Can you try commenting out the foreach loop that you quoted earlier and see if it helps. I’m not near a PC at the moment so I’m afraid I can’t offer much help. Maybe by the time I wake up tomorrow morning you’ll have it all worked out🧐

Yes loops and recursion are not considered in the parsing. We can try and support them.
The high cpu usage is not good though. Could it be related with that? Any hint from the profiler?
What happens in the CsoundUnity inspector? How many AudioChannels do you see?
Are you using CsoundUnityChilds?
Did you tested in the build? It could be an editor only issue.
I’ll have a closer look asap. Send me your csds!
Thank you for your interest, we’re happy to help and create together a great Csound tool!

Thanks for the quick respons @g_b. I just emailed you and sent the test .CSD files

A quick solution would be just commenting those lines

if you don’t use any CsoundUnityChild.

Edit: the funny part is that we developed CsoundUnityChild to consume less cpu :sweat_smile:

Sweet well removing that did cut down the CPU usage by about 3% which is definitely an improvement. If I’m planning on fetching each channel explicitly (minus the channel that handles the final output to the AudioSource itself) and don’t need to keep track of any other audio channels (which if I do I will explicitly fetch them using the Csound NativeMethods and provided get/set methods) is there a good portion of the code that I can simply remove which might help cut down the overall CPU usage?

If that’s too broad a question I guess my main question would be which portion of the code explicitly handles the routing of csounds to the AudioSource. Basically I don’t think I need some of the convenience methods provided as I believe my project violates the constraints of the use cases it was designed for

The code inside CsoundUnity OnAudioFilterRead (so ProcessBlock) is where all the magic happens, we grab the Csound output and copy it into the AudioSource. It’s very simple. There we also update all the available audio channels (found parsing the csd when you assign it in the inspector) to be used by any CsoundUnityChild in the scene. They implement their own OnAudioFilterRead to copy the selected audio channels in their AudioSource.
This to have multiple outputs in the scene with just one CsoundUnity (and so Csound) instance.

Ahhh okay cool, I’ll go ahead and much around with modifying that to see if I can get a significant reduction of the DSP CPU usage. Thanks for the info, very useful

1 Like

You can also remove from this line to the end of the foreach

Awesome, yeah I had removed that one as well just to see and it looks like that has me back down to expected CPU consumption, same as the test files provided in the sample scenes. Thanks so much for the help, I know this is a more specific case and I really appreciate it.