I did my first test getting an
EEL DSP script up and running under
Genome. Only a few minor syntax changes were necessary to get the script to compile under Visual Studio (though it did take the better part of a day to get it working). Overall I am happy with the features of the language and the fact that it has so few dependencies (and is generally written in ansii C, which hopefully means it's fairly fast). Initial speed tests were a bit disappointing. A simple FM synth (one operator, one modulator) ended up taking about 15-20% of my cpu time. Ideally I'd like a simple EEL module to take a percent or two. A C++ version of the same synth would take 0.1% or less of the cpu. So, I am currently looking into optimizing eel to tailor it to my needs a bit more. The eel core is fairly easy to understand (despite it's overly aggressive use of macros). These days I have been using
AMD Code Analyst, which is a nice, free version of VTune, for my optimization needs. The latest version runs right inside visual studio and doesn't require any special instrumentation. You just run the app and it starts collecting results. For those unfamiliar with these kinds of applications, basically they can tell you which functions are consuming cpu resources and then allow you to go line by line and see which lines are taking up the most time. This is essential for helping decide how to go about optimizing a large and complicated program. Obviously it doesn't make sense to optimize everything. Your code will become a mess. You want to target your optimizations to the inner loops - the things that are done the most often.
Most of the EEL execution time is spent looping through instructions, computing arithmetic operations and copying variables. I spotted some areas that could see huge gains in the arithmetic function. Basically there is a gigantic case statement which checks every possible combination of operation and variable type. Instead of one monolithic case statement I could see this being broken down into several nested comparisons and have at most 5 or 6 comparisons per operation, instead of the dozens that an average operation would take now. I also plan on moving up common operations and moving down uncommon ones. I am debating whether the instruction set can be simplified. The smaller the instruction set, the less time I'll be spending figuring out which instruction to execute. For my audio/dsp needs I am going to be operating on floating point numbers most of the time. Some variable types or operations might be removable. So, it should be interesting work to try to speed this up. Already I am learning a lot about VM's and the internals of scripting languages just by going through the code.
UPDATE:
In my searches I found that some compilers will convert a case statement into a what is known as a 'jump table' or 'branch table', which is basically an table of jump locations keyed by the variable you are evaluating in your switch statement. This is much faster than evaluating a huge case statement. Not sure if my compiler is doing that - if it is, then my optimization hopes are dimmed.
Right now I am toying around with making my own ASM-style scripting language with a very reduced opcode and ability set which. The language would be very specifically focused on processing streams of floating point audio data. I am hoping that these two things will make it a lot faster than EEL, which is fairly high level and provides a lot of functionality that isn't important for processing a stream of audio. It might be possible to combine EEL and this ASM language to cover both the high-level and low level bases. The language follows what I
posted previously. I coded the 'compiler' last night and I'll work on the VM tonight. I'll post when I get some results.
Labels: EEL, Genome, scripting