Concurrency in C++, the cross platform way

My blogging activity has been low recently, so here’s some C++ musings on concurrency/parallelism.

std::async woes

C++11 introduced low level threading facilities into the standard library, but also a potentially handy higher level function, std::async, that can run callables in other threads. Unfortunately the C++ standard left open how that should be implemented. Microsoft uses a task based implementation  for it since Visual Studio 2012 but C++ standard libraries from other vendors unfortunately use a threading based implementation. That means that the following code will likely launch 1000 threads with the non-Microsoft implementations :

void do_lots_of_stuff()
{
  for (int i=0;i<1000;++i)
    std::async(std::launch::any,[](){ //...suitably heavy processing here... });
  // Since we don't wait here for the threads to finish, this'll crash...
  // But this is example code, so just imagine here's something that waits
}

That is definitely something we don’t want, 1000 threads would have a considerable overhead. The Microsoft implementation on the other hand will attempt to use a more balanced number of threads, passing the work to be done via tasks into its Concurrency Runtime. (The Microsoft implementation doesn’t necessarily throttle the number of threads at maximum to be the number of CPU cores in the system, but it will likely be way less than 1000 threads with the code example above.)

Apple of course has its Grand Central Dispatch, aka libdispatch, that is designed to allow running code concurrently using a higher level API and which uses an optimized number of threads. Unfortunately, their C++ library does not take advantage of that for std::async. I can only speculate why : they simply don’t like developers using C++ and try to make it as unattractive as possible to use the C++ language on their precious elitist platforms. Making std::async not use Grand Central Dispatch could be considered one subtle way how they are nudging developers towards using Objective-C and Cocoa, which are not cross platform in any real world sense.

Fortunately, Sean Parent presented a replacement for std::async that uses Grand Central Dispatch on OS-X. The code is a bit hairy, but compiles and runs as expected. (The code seen in his slides in the “C++ seasoning” talk has an error, but the corrected version I got from Sean is given here.)

#include "dispatch/dispatch.h"
template <typename F, typename ...Args>
auto async(F&& f, Args&&... args)
-> std::future<typename std::result_of<F (Args...)>::type>
{
    using result_type = typename std::result_of<F (Args...)>::type;
    using packaged_type = std::packaged_task<result_type ()>;

    auto p = new packaged_type(std::bind(std::forward<F>(f), std::forward<Args>(args)...));
    auto result = p->get_future();
    dispatch_async_f(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
                     p, [](void* f_) {
        packaged_type* f = static_cast<packaged_type*>(f_);
        (*f)();
        delete f;
    });

    return result;
}

For Windows, we can have a simple wrapper for std::async, so we can write code that calls async the same way on both Windows and OS-X and get the desired behavior where the number of threads doesn’t explode :

template <typename F, typename ...Args>
auto async(F&& f, Args&&... args)
-> std::future<typename std::result_of<F (Args...)>::type>
{
    return std::async(std::launch::any,std::forward<F>(f),std::forward<Args>(args)...);
}

std::parallel_for_e…Oh crap, it doesn’t exist!

The C++ standards committee didn’t add even the simplest parallel algorithms for the C++11 standard library and they are not going to be seen in C++14, either. If we could have at least a parallel for loop that goes over a container and could do something with the elements, things would be a bit more happy…

Microsoft offers this in its Parallel Patterns Library, PPL. Use is rather simple since PPL is a proper C++ library, so it can use templates, iterators and lambdas :

#include "ppl.h"
void foo()
{
  std::vector<object_t> data(1000);
  Concurrency::parallel_for_each(data.begin(), data.end(), [](object_t& e) { // manipulate e });
}

Now, of course it’s not so great having to use a Microsoft specific library in our client code…And what about OS-X? Again, Apple’s Grand Central Dispatch also has a function that is similar to this, dispatch_apply_f. However, that is not only an Apple-specific API but also C, which is a language we don’t want to deal with directly in our client code.

So, I put on my thinking cap and was able to come up with a C++ function template, that uses the GCD/libdispatch API…(Someone probably has already done a better version of this but I wanted to see if I could manage to do it myself.)

#include "dispatch/dispatch.h"
template<typename It, typename F>
inline void parallel_for_each(It a, It b, F&& f)
{
    size_t count=std::distance(a,b);
    using data_t=std::pair<It,F>;
    data_t helper=data_t(a,std::forward<F>(f));
    dispatch_apply_f(count, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), &helper, [](void* ctx,size_t cnt)
    {
        data_t* d=static_cast<data_t*>(ctx);
        auto elem_it=std::next(d->first,cnt);
        (*d).second(*(elem_it));
    });
}

Again, some rather nasty looking code there, but anything goes as long as it’s in the bowels of library code!

Like for async(), we can do a simple wrapper function for Windows which calls PPL’s Concurrency::parallel_for_each :

#include "ppl.h"
template<typename It, typename F>
inline void parallel_for_each(It a, It b, F&& f)
{
    Concurrency::parallel_for_each(a,b,std::forward<F>(f));
}

Hopefully someone finds these code snippets interesting/useful. They are not guaranteed to be error-free or as efficient as possible. They rather serve as examples how Microsoft’s PPL and Apple’s Grand Central Dispatch/libdispatch can be wrapped into library C++ functions that can be used in a cross-platform manner in client code. (Mentioning Linux was omitted here but I believe the libdispatch stuff should work on it too, I just didn’t investigate and test that.)

Posted in Uncategorized | Tagged , , , , , | Leave a comment

HourGlass 1.4.5 for OSX

Here is finally a new build for OS-X :

http://ge.tt/5lffqOq1/v/0?c

It is based on the same code as the last public Windows release. So there isn’t anything new, Windows users need not worry that they are left out on anything. Future plans for HourGlass are still open. I am not going to develop the 1.x series further, I will only do fixes for bad bugs on OS-X.

It requires at least OS-X 10.7. (10.6 simply isn’t something I am willing to deal with anymore, so don’t ask about that.) It may contain new bugs compared to the last OS-X build, but if anyone reports them, there’s a chance they may get fixed…It might not even run at all since I didn’t exactly remember the procedure I used last year when I did the OS-X builds…But please do report any problems, so I can look if they are fixable.

Posted in Uncategorized | 1 Comment

How’s HourGlass? Do I now drink JUCE? Qt no longer so cute?

I haven’t worked on HourGlass at all for a few months. Now that I’ve gotten more familiar with JUCE, it seems there could be a possibility I might rewrite HourGlass in some form using JUCE. That would have the benefit that making a plugin version would finally feasibly be possible. The recently released CDP front-end plugin is actually mostly developed as a standalone application (binaries of that have not been publicly available yet), which I every now and then build and test in the Reaper plugin mode. With JUCE based code it’s quite transparent to switch between a standalone application and a plugin with the same code base.

I am not sure yet what I am going to do with HourGlass. I feel very tempted to just drop the Qt based version completely. While Qt is an excellent framework, I’ve found it to become less and less relevant for myself. It’s very bad for doing plugins of any kind, except plugins for host applications that themselves are written with Qt. (And even then, there are the problems of C++ ABI compatibility and so on…) Qt no longer develops the traditional Qt Widgets module. They instead prefer to develop their Qml based GUI system, which isn’t very attractive for me. (Qml has a TON of runtime dependencies, it’s not C++ etc…) They nudge people towards using Qml in new code and I don’t like that.

One possibility how I might proceed is that I could extract and adapt the HourGlass audio processing code from the current Qt-based HourGlass code base and integrate that code into the CDP front-end code. The CDP programs offer all kinds of granular sound processing algorithms, but none of the CDP programs do granular processing exactly like HourGlass. (At least as far as I’ve found…) So having the HourGlass granulation/fragmentation processing available in the CDP front-end could make sense. I might need to rename the CDP front-end to something else then, though…

JUCE is not without its own problems, of course. But I’ve started to feel like it is the more appropriate thing for me to use.

I guess these were just random ramblings…

Posted in Uncategorized | 1 Comment

Oh noes, there could be a null pointer!

It’s been some time since I wrote anything about C++ programming, so here’s something. Sorry for users of HourGlass and other softwares of mine if this isn’t of much interest. ;) (I will probably start a separate blog specifically about programming later this year.)

Ideally one’s C++ code would never attempt to use an object via a null pointer, but in some cases having the possibility of a null pointer is just convenient to have. Maybe it’d be too tiresome to write an object that has some well defined null/empty/do-nothing state or whatever.

Class whose methods will be called in the examples :

class MyObject
{
public:
    double m_x=0.5;
    double foo() { m_x+=0.1; return sin(m_x)+cos(m_x); }
    void not_much() { }
    double borken_sum(double a, double b) { return m_x+a+b; }
    std::string mangle(std::string a)
    {
        std::reverse(a.begin(),a.end());
        return std::to_string(m_x)+a;
    }
};

The usual way to deal with a pointer that can be either null or valid is something like :

// MyObject* m_object ends up as nullptr or a valid pointer
// in some way before this code is run
// foo() of valid object should return a double
if (m_object!=nullptr)
  return m_object->foo(); 
else
  return 0.0; 

Or, more tersely with the terrible ternary operator :

return m_object!=nullptr ? m_object->foo() : 0.0;

I today came up(*) with an alternative solution that involves quite a hairy helper function but I kind of like this solution, assuming it actually works properly in most scenarios. (I didn’t extensively test this yet. There could be cases where the compiler gives an error or maybe the performance of making an object method call this way is horribly bad. Maybe Clang and GCC totally hate this. This was tested with the Visual Studio 2013 C++ compiler.)

The helper function in all its insanity :

template<typename U,typename F,typename... Args>
auto safe_call(U* ptr,F f,Args... args) -> decltype(std::mem_fn(f)(ptr,args...))
{
    if (ptr!=nullptr)
        return std::mem_fn(f)(ptr,args...);
    return decltype(std::mem_fn(f)(ptr,args...))();
}

Usage in client code :

return safe_call(m_object,&MyObject::foo);

In this version, no annoying additional control flow needs to be written, “nullptr” doesn’t need to be written, “m_object” doesn’t need to be written twice and the fallback value of 0.0 will be default constructed from the type the MyObject::foo() method returns.

Due to the variadic template, member functions with 1 or more arguments can also be used. The auto return type in the helper function also works for member functions that don’t return a value.

Additional usage examples :

double a=safe_call(m_object,&MyObject::borken_sum,2.0,1.0);
std::cout << safe_call(m_object,&MyObject::mangle,"Cat Attack") << "\n";
safe_call(m_object,&MyObject::not_much);

The downside is having to write the names of the class and the method with the &ClassName::MethodName notation.

Of course the safe_call-style technique doesn’t buy much if several methods of an object need to be called in a row. The following usual solution will work just fine and expresses the intent :

if (m_object!=nullptr)
{
  double a=m_object->foo();
  m_object->not_much();
  auto r=m_object->mangle("ooF");
} 

(*) No doubt this has been invented by someone else before me but I wanted to see if I could write it myself.

Posted in C++, Programming | Leave a comment

CDP frontend Reaper extension plugin

edit 10th November 2014 : Pre 5 for Windows and OS-X. Notable changes :

-Envelope segments can be curved by Alt+dragging the segments.
-CDP processings which require doing the processing by splitting stereo files into mono files are now processed in parallel, hopefully resulting in speedups
-The plugin adds another action “Xenakios : Reset CDP front-end”, which hopefully will reset the plugin to a fresh state if it ends up not working, without having to restart Reaper.
-OSX version should now display more errors when appropriate, instead of just setting a non-existing file on the output waveform. (This is still not working completely…)

edit 22nd August 2014 : Pre 4 for Windows and OS-X. Preliminary support for processing stereo files with CDP programs that don’t support stereo directly. (Such as all the spectral processors and the processors in the “Distort” group.) Some other tweaks and fixes.

edit 3rd August 2014 : Pre 3 for Windows and OS-X. Modify Speed processor was added. (For resampled pitch/time processing.) More parameters of the Texture Simple processor can be automated. Some misc fixes. OS-X build now only has the 64 bit version.

edit 31st July 2014 : Preliminary OS-X build uploaded. I was able to make the plugin GUI only work so that it stays on top of everything, which is very annoying, but less annoying than it disappearing behind Reaper’s window when clicking outside the plugin GUI…Hopefully that problem can be solved at some point.

edit 29th July 2014 : pre2 builds uploaded. Contains various fixes and the ability to zoom and scroll the input sound waveform. (The zoomscroll-bar is between the input and output waveforms.)

I am finally making the first public release of the C++/Juce based CDP frontend I’ve worked on for the last 5 weeks or so. Thanks to Oli Larkin for working on the OS-X build! (Unfortunately it didn’t materialize for this first release, though.)

If you don’t already know what the Composer’s Desktop Project is, please read before trying to use the plugin to decide if this something you would likely be interested in trying to test :

http://www.composersdesktop.com/

To use this, you must have the Composer’s Desktop Project installed, available from :

http://www.unstablesound.net/cdp.html

-The plugin allows you to bypass setting the CDP_SOUND_EXT environment variable which is mentioned somewhere in the CDP documentation that it must be set for things to work. (If the environment variable is not set, the plugin sets it temporarily.)

-The plugin will on first run ask you to locate the CDP binaries location. This is the folder with files such as “pvoc.exe”, “modify.exe” and “distort.exe” within the CDP installation.

-The plugin adds one new action into Reaper : “Xenakios : Show/hide CDP front-end” which you should find from the Reaper actions window. The action is not added to any menu in Reaper or given a default keyboard shortcut.

-When the plugin window has focus, the following keyboard shortcuts are active :

Insert-key : Import the selected Reaper media item
Home-key : Toggle automatic rendering after settings (parameter sliders, automation envelopes, the time waveform time selection) have been altered. You might want to have this turned off when you know you want to alter several settings/automation points and the rendering delay is too short to reach the desired GUI elements before the automatic rendering is triggered.
Delete-key : Removes the selected area from the sound file or envelope points of the selected area. (Depending on whether the Waveform or Envelope button in the top left is active.)

-Please use this plugin with Reaper 4.7 or newer only! Reaper versions before 4.7 have a bug that crashes during the realtime preview.

The front end has various omissions, quirks and defects at this point, but I hope it will be somewhat useful already. Some of the things are quite tricky to implement ideally because everything works by running command line programs in the background, after all…But I hope I will be able to later implement better solutions to some of the issues.

It only has a limited selection of the CDP processing programs available at this point, as some of them require much more complicated GUIs and logic than is currently implemented. (And some of the suitable programs I just haven’t added yet.)

Many of the CDP programs only process mono files. This has been worked around in the Pre 4 by splitting stereo files into mono files, then processing them separately with the mono-only programs and then joining the mono files back to a stereo file. This can in some cases cause the channels to become completely decorrelated and the original stereo image will be lost. But since this workaround is the only possible, it’s provided in the hopes it will be useful/interesting in some situations.

64 bit plugin : (Windows 7 or newer) :

http://ge.tt/61VUKC42

32 bit plugin : (Windows 7 or newer) :

http://ge.tt/5waxJC42

OS-X plugin : (Tested only on OS-X 10.9, 64 bit. Might work on 10.7 or 10.8 or 10.10. Don’t ask for 10.6 support, that won’t happen.) :

http://ge.tt/8mBPOC42

To comply with the Juce licensing model, the source code is GPL-licensed and is available from the following link :

https://bitbucket.org/xenakios/reaper-cdp-frontend-extension-plugin/src

Posted in Uncategorized | 8 Comments

Python scripts for using CDP in Reaper

Again a little side project to distract myself from making progress with HourGlass 2…

If you don’t know what the Composer’s Desktop Project or Reaper is, this set of Python scripts to be run from Reaper probably isn’t something you want to try.

Prerequisites :

  • You have confirmed the CDP programs will run for you (ie, you have installed the CDP package, set the annoying environment variable for wav-files, done some test runs from the command line/SoundLoom/Soundshaper etc)
  • You have installed Python 3.x and set up Reaper to use it for ReaScript (Python 2.7.x might work too, but I haven’t tested)

Download the zip of the Python scripts :

http://ge.tt/60IhTti1/v/0?c

If ge.tt appears to be down, you can download the source codes as a zip archive from the Bitbucket repo :

https://bitbucket.org/xenakios/cdp-python-reascripts/get/c5316792a198.zip

There are 15 .py files. All except one (cdp_helpers.py) may be loaded into Reaper as new Python ReaScript actions. They allow you to process the selected Reaper media item with the CDP sound process in question.

There unfortunately is a set up step which for now has to be done manually by editing the cdp_helpers.py file. :( You must change the line with the text :


cdp_prog_dir=""

to something like


cdp_prog_dir="C:\\Portable_Apps\\cdpr700-InstallPC\\_cdp\\_cdprogs\\"

Where you would substitute the actual location of the CDP binaries on your machine inside the “”. (This will be the CDP installation directory with files such as blur.exe, pvoc.exe, envel.exe) Note that on Windows, each \ needs to be substituted with \\ instead.

In regards to the CDP processings themselves, you should refer to the CDP documentation. I’ve tried naming the script files so that the corresponding CDP processes can be found from the documentation without too much trouble. The scripts obviously don’t cover all the CDP processings available, more will be added in the future. The 14 scripts just provide some examples which I chose somewhat randomly or according to my own taste.

Processing obviously happens offline but is not in any way destructive, that is, the original audio files in the Reaper project are never modified in any way. The new processed file will be added as a new take into the Reaper media item. If the processing is supposed to change the length of the material, the item length is changed to correspond to the new length. (This might be nice to have optionally, I guess…?)

The first limitation at the moment is that several of the processings will only work with mono audio source files. So, for those processors, when you have a stereo file, you should change the selected item’s channel mode in Reaper to mono and then use the Reaper glue action before running those CDP processes. There is a possible hack around this, which I will probably add to the cdp_helper.py file later.

The second limitation is that the facilities of many of the CDP programs to allow time varying parameters (aka automation) are not available from these scripts. In principle, this could be enabled by parsing break point envelopes from the dialog box text fields. So for example something like [0.0,0.1,10.0,1.0] could be written in a text field to automate a parameter so that it starts at the value 0.1 at the time 0.0 and proceeds to value 1.0 at the time 10.0. This however seems terribly clunky and I am not sure if it would be worth it implementing it.

The third limitation is that no audio preview of the processings is available. This could in principle be implemented, but not really with Python and ReaScript. For now, the only way to know how the processing ends up sounding is to enter some parameter values and run the process. If you are not happy with the results, switch back to the original take in Reaper and rerun the same or different CDP process.

I am not sure if these work on OS-X or not…But I just updated the download link with an obvious fix for the cdp_helpers.py file.

If you do cool and/or useful changes/additions to the scripts, it would be appreciated if you would let me know of those so I could maybe add them to the source code repo, hosted at  https://bitbucket.org/xenakios/cdp-python-reascripts/overview

I’ll expand this blog post a bit later but hopefully these instructions are enough to allow trying these.

Posted in Uncategorized | 4 Comments

What’s been going on?

I’ve taken some leave from developing HourGlass and been updating/rewriting an old Reaper extension plugin (from around 2009) that does pitch and time processing of media items in Reaper. I was prompted to do this when a 64 bit build of the plugin was requested at the Reaper forum a few weeks ago. I had already done a 64 bit build  of the plugin quite a long time ago, but I very quickly noticed the code had all kinds of flaws and worse, serious bugs where invalid memory was accessed, threads were writing and reading the same objects at the same time without locking and so on. For some reason, the 32 bit build of the plugin had worked seemingly OK.

The update or rather rewrite has involved the following and more :

  • Removal of numerous global variables. (Still not completely eliminated as only one instance of the plugin can run anyway currently and removing the remaining global variables would be a bit labor intensive.)
  • Remove almost all explicit uses of C++ new and delete operators and use smart pointers and std::vectors instead. The old code had a very distasteful hodgepodge of std::vectors and allocating buffers via operator new[], usually forgetting to release them with delete[]. Consistency is sanity, all dynamic buffers are now std::vectors. I wonder why I hadn’t thrown a lonely malloc()/free() pair into the old code, too…
  • Object ownerships were introduced. For example, in the old code the automation envelopes were for some reason in a global std::vector. Allocated via pointers for no purpose, of course. In the new code the audio processors themselves create and manage the envelope objects. And the envelopes are managed just as values, not pointers. (ie, in the old code there was std::vector<envelope*> as a global variable, in the new code the DSP processor class has a member std::vector<envelope>.)
  • Although deep class hierarchies can be problematic, I introduced a new base class that handles common things for the 2 derived DSP processor classes (for resampled pitch processing and for independent pitch/time/formant processing). The GUI code no longer needs to do insane checks about which class and which object instance should be accessed. The deeper class hierarchy was clearly a better design here. Adding new processor types is around 100x more feasible now than it was in the old code.
  • State saving/loading to/from disk was added, handled with JSON. This required writing quite a lot of annoying boilerplate code, but on the other hand clarified what the object states really consist of.

The plugin is in a pretty good state at the moment, I suppose I will keep working on it for a week or two. Then I will hopefully return to working on HourGlass 2. (A public release of HG 2 is still far in the future. An optimistic estimate would be around July 2014.)

Posted in Uncategorized | 1 Comment