[haskell-art] Haskell audio I/O packages
John Lato
jwlato at gmail.com
Mon Dec 8 12:59:50 GMT 2008
On Fri, Dec 5, 2008 at 7:04 PM, stefan kersten <sk at k-hornz.de> wrote:
> Henning Thielemann wrote:
>> Thank you for this benchmark! I'm particularly interested in
>> StorableVector because I hacked it quite a bit and use it for my own
>> signal processing.
>>
>> I would also like to know how Fusion+Inlining improves the picture, but I
>> do not know if there is anything to fuse at all in this simple example.
>> Can you show us the actual test you run? I would then compare with my
>> fusing signal data type from the synthesizer package.
>
> yes, thanks john, very interesting ... i'd also be interested in the
> benchmarking code ;)
I'll try to post the code tonight after work. I'll also post the
library versions I tested, which in all cases were the latest
available on Hackage at the time I ran my tests. One thing to keep in
mind is that, in general, the benchmarking code is pretty simple. I
was trying to approach this from the point of view of an average user
(e.g. me), who may not be familiar with all the Haskell optimization
strategies.
I doubt there's anything to fuse in this example, but I don't know
much about fusion implementations. I have tried inlining certain
functions, but either there was no change (which was my expectation),
or a slight slowdown.
>
>>> hsndfile - a recursive I/O function reads a chunk from the file (using
>>> IOCArray type) and accumulates the maximum values from each chunk. I
>>> attempted to create a framework like used for HSoundFile-3, however
>>> performance dropped dramatically; I suspect the slowdown is mostly
>>> from the process of freezing mutable arrays to immutable arrays.
>
> for CArray i've been using unsafeFreezeIOCArray, which does an O(1)
> conversion (simply keeping the pointer to the mutable array).
Thanks, I'll try that.
>
>>> For chunked data types, all data is with chunk size 1000.
>>> All timing/memory data is the median value from multiple runs. In
>>> general different runs had very similar performance.
>>>
>>> Timing results:
>>> HSoundFile-3, StorableVector - real 16.5s
>>> HSoundFile-3, UArr - real 15.7s
>>> HSoundFile-3, List - real 17.6s
>>
>> Is this the plain Prelude [] type? Why are List and StorableVector similar
>> in speed?
Yes, it's the plain Prelude [] type. I expect they're similar in
speed because of the particular implementation of AudioBuffer in
HSoundFile-3. Specifically, the AudioBuffer class has a fromList
function which is used to create the buffer from a Data.Binary decode
operation. The UArr API is somewhat optimized for this use case,
however I believe it's relatively inefficient for StorableVector. If
someone more familiar with StorableVector were to write the
AudioBuffer instance, I think it would perform better.
Adding specialized instances for AudioBuffer UArr and AudioBuffer
StorableVector would likely produce a significant gain; about 10% for
UArr and probably less for StorableVector.
Changing the AudioBuffer class to avoid the intermediate List is
trickier. Last time I tried, I don't believe I found a successful
approach.
Given my results, my next approach will be an Enumerator API that uses
hsndfile to actually read from the file. I think that would have
nearly all the performance of hsndfile with a functional, composable
interface.
More information about the haskell-art
mailing list