I am trying to compare the performance of boost::multi_array to native dynamically allocated arrays, with the following test program:
#include <windows.h>
#define _SCL_SECURE_NO_WARNINGS
#define BOOST_DISABLE_ASSERTS
#include <boost/multi_array.hpp>
int main(int argc, char* argv[])
{
const int X_SIZE = 200;
const int Y_SIZE = 200;
const int ITERATIONS = 500;
unsigned int startTime = 0;
unsigned int endTime = 0;
// Create the boost array
typedef boost::multi_array<double, 2> ImageArrayType;
ImageArrayType boostMatrix(boost::extents[X_SIZE][Y_SIZE]);
// Create the native array
double *nativeMatrix = new double [X_SIZE * Y_SIZE];
//------------------Measure boost----------------------------------------------
startTime = ::GetTickCount();
for (int i = 0; i < ITERATIONS; ++i)
{
for (int y = 0; y < Y_SIZE; ++y)
{
for (int x = 0; x < X_SIZE; ++x)
{
boostMatrix[x][y] = 2.345;
}
}
}
endTime = ::GetTickCount();
printf("[Boost] Elapsed time: %6.3f seconds\n", (endTime - startTime) / 1000.0);
//------------------Measure native-----------------------------------------------
startTime = ::GetTickCount();
for (int i = 0; i < ITERATIONS; ++i)
{
for (int y = 0; y < Y_SIZE; ++y)
{
for (int x = 0; x < X_SIZE; ++x)
{
nativeMatrix[x + (y * X_SIZE)] = 2.345;
}
}
}
endTime = ::GetTickCount();
printf("[Native]Elapsed time: %6.3f seconds\n", (endTime - startTime) / 1000.0);
return 0;
}
I get the following results:
[Boost] Elapsed time: 12.500 seconds
[Native]Elapsed time: 0.062 seconds
I can't believe multi_arrays are that much slower. Can anyone spot what I am doing wrong?
I assume caching is not an issue since I am doing writes to memory.
EDIT: This was a debug build. Per Laserallan's suggest I did a release build:
[Boost] Elapsed time: 0.266 seconds
[Native]Elapsed time: 0.016 seconds
Much closer. But 16 to 1 still seems to high to me.
Well, no definitive answer, but I'm going to move on and leave my real code with native arrays for now.
Accepting Laserallan's answer because it was the biggest flaw in my test.
Thanks to all.
On my machine using
g++ -O3 -march=native -mtune=native --fast-math -DNDEBUG test.cpp -o test && ./test
I get
[Boost] Elapsed time: 0.020 seconds
[Native]Elapsed time: 0.020 seconds
However changing const int ITERATIONS
to 5000
I get
[Boost] Elapsed time: 0.240 seconds
[Native]Elapsed time: 0.180 seconds
then with ITERATIONS
back to 500
but X_SIZE
and Y_SIZE
set to 400
I get a much more significant difference
[Boost] Elapsed time: 0.460 seconds
[Native]Elapsed time: 0.070 seconds
finally inverting the inner loop for the [Boost]
case so it looks like
for (int x = 0; x < X_SIZE; ++x)
{
for (int y = 0; y < Y_SIZE; ++y)
{
and keeping ITERATIONS
, X_SIZE
and Y_SIZE
to 500
, 400
and 400
I get
[Boost] Elapsed time: 0.060 seconds
[Native]Elapsed time: 0.080 seconds
If I invert the inner loop also for the [Native]
case (so it is in the wrong order for that case), I get, unsurprisingly,
[Boost] Elapsed time: 0.070 seconds
[Native]Elapsed time: 0.450 seconds
I am using gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5
on Ubuntu 10.10
So in conclusion:
Your test is flawed.
What you're likely seeing is the result of your optimizing compiler seeing that most or all of your "native array" loops can be removed. The same is theoretically true of your boost::MultiArray loops, but MultiArray is probably complex enough to defeat your optimizer.
Make this small change to your testbed and you'll see more true-to-life results: Change both occurances of "= 2.345
" with "*= 2.345
" and compile again with optimizations. This will prevent your compiler from discovering that the outer loop of each test is redundant.
I did it and got a speed comparison closer to 2:1.
Are you building release or debug?
If running in debug mode, the boost array might be really slow because their template magic isn't inlined properly giving lots of overhead in function calls. I'm not sure how multi array is implemented though so this might be totally off :)
Perhaps there is some difference in storage order as well so you might be having your image stored column by column and writing it row by row. This would give poor cache behavior and may slow down things.
Try switching the order of the X and Y loop and see if you gain anything. There is some info on the storage ordering here: http://www.boost.org/doc/libs/1_37_0/libs/multi_array/doc/user.html
EDIT: Since you seem to be using the two dimensional array for image processing you might be interested in checking out boosts image processing library gil.
It might have arrays with less overhead that works perfectly for your situation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With