472,980 Members | 1,776 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,980 software developers and data experts.

Contiguous allocation of multi-dimensional vector

nw
Hi,

We've been having a discussion at work and I'm wondering if anyone
here would care to offer an opinion or alternative solution. Aparently
in the C programming HPC community it is common to allocate
multidimentional arrays like so:

int *v_base = (int *) malloc(1000000*sizeof(int));
int **v = (int **) malloc(1000*sizeof(int *));

for(int i=0;i<1000;i++) {
v[i] = v_base+(i*1000);
}

The logic behind this is that the entire multi-dimensional array will
be contiguous in memory and therefore it is more likely that the whole
array will be loaded in to cache, improving access time.

The following workaround I believe will simulate similar behaviour
using the STL:

vector<intv_base(1000000);
vector<int *v;

for(int i=0;i<1000;i++) {
v.push_back(&v_base[0]+(i*1000));
}

However will obviously break if you use insert or remove anywhere, and
doesn't seem like a great idea. The standard way of allocating this
two dimensional array as I understand it is:

vector<vector<int v(1000,vector<int>(1000));

So I guess my question is this: Is there any advantage to allocating
the vector contiguously or should the normal STL allocation method
place the vectors contiguously in memory? Is there likely to be much
vector overhead placed between the 1d vector<int>s such as the size of
the array?

My gut feeling is that the normal STL way will produce similar
results, and the tests I've done seem to back this up, but I'd be
interested in hearing other peoples opinions.

Any suggestions gratefully received and my apologies if this has been
asked previously or in the FAQ and I missed it.

Aug 9 '07 #1
7 3821
joe
From: nw
>

Hi,

We've been having a discussion at work and I'm wondering if anyone
here would care to offer an opinion or alternative solution. Aparently
in the C programming HPC community it is common to allocate
multidimentional arrays like so:

int *v_base = (int *) malloc(1000000*sizeof(int));
int **v = (int **) malloc(1000*sizeof(int *));

for(int i=0;i<1000;i++) {
v[i] = v_base+(i*1000);
}
Hmmmm, back in the day, I wouldn't have bothered with v. Any cell can
be
directly calculated for an array of v[HEIGHT, WIDTH] with WIDTH * (row
- 1)
+ column. Of course, memory was at a premium.
>
The logic behind this is that the entire multi-dimensional array will
be contiguous in memory and therefore it is more likely that the whole
array will be loaded in to cache, improving access time.
and there is only one allocation per array (malloc/free can be pretty
time
consuming). Of course, on the other side of the fence, it may be
easier to
come up to 1000 4000 byte blocks than one 4000000 byte block.
>
The following workaround I believe will simulate similar behaviour
using the STL:

vector<intv_base(1000000);
vector<int *v;

for(int i=0;i<1000;i++) {
v.push_back(&v_base[0]+(i*1000));
}

However will obviously break if you use insert or remove anywhere, and
doesn't seem like a great idea. The standard way of allocating this
two dimensional array as I understand it is:
This is a non-issue because you would never insert or delete in a
multidimensional
array unless you were explicitly supporting ragged arrays and that is
a
different sort of problem.
>
vector<vector<int v(1000,vector<int>(1000));

So I guess my question is this: Is there any advantage to allocating
the vector contiguously or should the normal STL allocation method
place the vectors contiguously in memory? Is there likely to be much
vector overhead placed between the 1d vector<int>s such as the size of
the array?

My gut feeling is that the normal STL way will produce similar
results, and the tests I've done seem to back this up, but I'd be
interested in hearing other peoples opinions.

Any suggestions gratefully received and my apologies if this has been
asked previously or in the FAQ and I missed it.
The best answer would depend upon what you are using the arrays for.
The
problem with a vector of vectors is that you lose a lot of locality of
reference
and therefore may well have more cache misses; there is another layer
of indirection; and since insert/erase is available, you have the
possibility
of turning your multidimensional array into a ragged array without
even
half trying.

The good news is that this is C++ and you can wrap whatever logic you
choose
in a class and only allow the operations which make sense.
Personally, I
would probably start off with something like:

template <typename T, size_t N, size_t M>
struct marray
{
typedef size_t size_type;
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;

reference at(size_type x, size_type y)
{
return m_array[x,y];
}

const_reference at(size_type x, size_type y) const
{
return m_array[x,y];
}

private:
T m_array[N,M];
};

And flesh it out with what I needed (iterators, row_iterators, etc).
Then I
could choose whether I wanted it dynamic or not and it would be a
single
allocation either way. If I needed a ragged array, well that would be
different.

joe


Aug 9 '07 #2

nw <ne*@soton.ac.ukwrote in message...
>
However will obviously break if you use insert or remove anywhere, and
doesn't seem like a great idea. The standard way of allocating this
two dimensional array as I understand it is:

vector<vector<int v(1000,vector<int>(1000));
Or:

{// ------------
std::vector< std::vector< int Array2( 3, 3 );

for( std::size_t x(0); x < Array2.size(); ++x ){
std::cout<<"array.at("<<x<<") address="
<<std::hex<<&Array2.at(x)
<<std::dec<<std::endl;
for( std::size_t y(0); y < Array2.at( x ).size(); ++y ){
std::cout<<" array.at("<<x<<").at("<<y
<<") address="<<std::hex<<&Array2.at(x).at(y)
<<std::dec<<std::endl;
} // for(y)
} // for(x)
}// ------------

To answer all your questions: test and profile it.

--
Bob R
POVrookie
Aug 9 '07 #3
On Aug 9, 10:07 pm, joe <jgr...@DoubleTake.comwrote:
From: nw
Hi,
We've been having a discussion at work and I'm wondering if anyone
here would care to offer an opinion or alternative solution. Aparently
in the C programming HPC community it is common to allocate
multidimentional arrays like so:
int *v_base = (int *) malloc(1000000*sizeof(int));
int **v = (int **) malloc(1000*sizeof(int *));
for(int i=0;i<1000;i++) {
v[i] = v_base+(i*1000);
}

Hmmmm, back in the day, I wouldn't have bothered with v. Any cell can
be
directly calculated for an array of v[HEIGHT, WIDTH] with WIDTH * (row
- 1)
+ column. Of course, memory was at a premium.
The logic behind this is that the entire multi-dimensional array will
be contiguous in memory and therefore it is more likely that the whole
array will be loaded in to cache, improving access time.

and there is only one allocation per array (malloc/free can be pretty
time
consuming). Of course, on the other side of the fence, it may be
easier to
come up to 1000 4000 byte blocks than one 4000000 byte block.
The following workaround I believe will simulate similar behaviour
using the STL:
vector<intv_base(1000000);
vector<int *v;
for(int i=0;i<1000;i++) {
v.push_back(&v_base[0]+(i*1000));
}
However will obviously break if you use insert or remove anywhere, and
doesn't seem like a great idea. The standard way of allocating this
two dimensional array as I understand it is:

This is a non-issue because you would never insert or delete in a
multidimensional
array unless you were explicitly supporting ragged arrays and that is
a
different sort of problem.
vector<vector<int v(1000,vector<int>(1000));
So I guess my question is this: Is there any advantage to allocating
the vector contiguously or should the normal STL allocation method
place the vectors contiguously in memory? Is there likely to be much
vector overhead placed between the 1d vector<int>s such as the size of
the array?
My gut feeling is that the normal STL way will produce similar
results, and the tests I've done seem to back this up, but I'd be
interested in hearing other peoples opinions.
Any suggestions gratefully received and my apologies if this has been
asked previously or in the FAQ and I missed it.

The best answer would depend upon what you are using the arrays for.
The
problem with a vector of vectors is that you lose a lot of locality of
reference
and therefore may well have more cache misses; there is another layer
of indirection; and since insert/erase is available, you have the
possibility
of turning your multidimensional array into a ragged array without
even
half trying.

The good news is that this is C++ and you can wrap whatever logic you
choose
in a class and only allow the operations which make sense.
Personally, I
would probably start off with something like:

template <typename T, size_t N, size_t M>
struct marray
{
typedef size_t size_type;
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;

reference at(size_type x, size_type y)
{
return m_array[x,y];
}

const_reference at(size_type x, size_type y) const
{
return m_array[x,y];
}

private:
T m_array[N,M];

};

And flesh it out with what I needed (iterators, row_iterators, etc).
Then I
could choose whether I wanted it dynamic or not and it would be a
single
allocation either way. If I needed a ragged array, well that would be
different.

joe- Hide quoted text -
no double subscription in c++([x,y]).one must use two single
subscriptions([x][y]) or you are discusing conceptually(not
syntactically) and [x,y] is considered a function(not a c++
operator).
I think variadic templates(to come) with variable number of unsigned
argument will solve the problem with no overhead(codding time/run time/
run memory):

template<typename T,unsigned args... multiDimArr;

regards,
FM.

Aug 9 '07 #4
joe
On Aug 9, 5:51 pm, terminator <farid.mehr...@gmail.comwrote:
no double subscription in c++([x,y]).one must use two single
subscriptions([x][y]) or you are discusing conceptually(not
syntactically) and [x,y] is considered a function(not a c++
operator).
Arg!! I know that, somehow it didn't get typed that way though.
I think variadic templates(to come) with variable number of unsigned
argument will solve the problem with no overhead(codding time/run time/
run memory):

template<typename T,unsigned args... multiDimArr;
You are correct, but it will be many years before that gets out into
the mainstream,
so I wouldn't be writing too much code like that.

joe

Aug 10 '07 #5
On Aug 9, 5:49 pm, nw <n...@soton.ac.ukwrote:
We've been having a discussion at work and I'm wondering if anyone
here would care to offer an opinion or alternative solution. Aparently
in the C programming HPC community it is common to allocate
multidimentional arrays like so:
int *v_base = (int *) malloc(1000000*sizeof(int));
int **v = (int **) malloc(1000*sizeof(int *));
for(int i=0;i<1000;i++) {
v[i] = v_base+(i*1000);
}
The logic behind this is that the entire multi-dimensional array will
be contiguous in memory and therefore it is more likely that the whole
array will be loaded in to cache, improving access time.
The following workaround I believe will simulate similar behaviour
using the STL:
vector<intv_base(1000000);
vector<int *v;
for(int i=0;i<1000;i++) {
v.push_back(&v_base[0]+(i*1000));
}
However will obviously break if you use insert or remove anywhere, and
doesn't seem like a great idea.
You mean that it makes it impossible for v[0] to have a
different number of elements than v[1]. Depending on the
application, that could be an advantage, rather than a
disadvantage.
The standard way of allocating this two dimensional array as I
understand it is:
vector<vector<int v(1000,vector<int>(1000));
It depends on the use. The *standard* way of handling
multidimensional arrays in C++ is to write your own class to do
so, with an overloaded operator[] which returns a "proxy" on
which operator[] is also defined. (Note that in this case, int*
would be an adequate proxy.) Then, you can do pretty much
whatever works in the implementation; I'd probably just use a
one dimension vector, and calculate the indexes.
So I guess my question is this: Is there any advantage to allocating
the vector contiguously
There certainly could be, for some applications. To begin with,
you'll use less total memory---if the inner dimension is 1000,
it's probably not distinctive, but for something like:
std::vector< std::vector< int v( 1000000,
std::vector< int >( 5 ) ) ;
the difference could be enormous.
or should the normal STL allocation method
place the vectors contiguously in memory? Is there likely to be much
vector overhead placed between the 1d vector<int>s such as the size of
the array?
Who knows? It could easily vary, even from one run to the next.
My gut feeling is that the normal STL way will produce similar
results, and the tests I've done seem to back this up, but I'd be
interested in hearing other peoples opinions.
The real question is whether whatever method you feel most
comfortable with is fast enough. If so, don't bother looking
any further. Personally, for a mathematical matrix, I prefer
the single dimension array, calculating the index. It makes it
impossible to violate the invariant that all of the sub-arrays
have the same size. But if that caused performance problems
(e.g. because multiplication was very slow on my machine), I'd
try something else.

Just make sure that whatever you actually do is behind the
firewall of a class definition, so you can change it at will
without affecting client code.

--
James Kanze (GABI Software) email:james.ka...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Aug 11 '07 #6
On Aug 10, 2:59 pm, joe <jgr...@DoubleTake.comwrote:
On Aug 9, 5:51 pm, terminator <farid.mehr...@gmail.comwrote:
no double subscription in c++([x,y]).one must use two single
subscriptions([x][y]) or you are discusing conceptually(not
syntactically) and [x,y] is considered a function(not a c++
operator).

Arg!! I know that, somehow it didn't get typed that way though.
I think variadic templates(to come) with variable number of unsigned
argument will solve the problem with no overhead(codding time/run time/
run memory):
template<typename T,unsigned args... multiDimArr;

You are correct, but it will be many years before that gets out into
the mainstream,
so I wouldn't be writing too much code like that.

joe
if your compiler is elegant in recursive templates you can:

template <typename elem,unsigned sz >
struct array{
typedef elem Telement;
enum{
Nsize=sz,
dim=1
};
...//etc
};

template<typename arr, unsigned n>
struct multi_array{
typedef typename arr::Telement Telement;
enum{
Nsize=n*arr::Nsize,
dim=arr::dim+1
};
...//etc
};

multi_array< multi_array <array <int,10,11 , 12 >
arr3D_10_11_12int;

regards,
FM.

Aug 14 '07 #7
joe
On Aug 14, 1:08 pm, terminator <farid.mehr...@gmail.comwrote:
>
if your compiler is elegant in recursive templates you can:
[crafty recursive template removed]

Quite clever. Probably a bit of overkill for any matrix problem I
have had, but still quite clever. Seriously though, unless I were
developing a library that supported such things, I would probably
still opt for individual implementations/specializations for the
problem set I actually had rather than a recursive template solution.
In other words, unless I were developing the code to be a matrix
library that could handle any dimension matrix, I personally, would
rather have the two or three specializations for matrixes that I
actually need, rather than a recursive template that handles every
possible kind of matrix. The reason is two fold. 1) Debugger
technology available to me makes debugging recursive template code
much more difficult than straight forward template code (although that
can be a challenge too at times). 2) Current optimizer technology
hasn't performed the wonders for me that sophisticated template
programmers posit that it should be able to perform. That is, the
code actually generated isn't as good as far as I can tell. Your
mileage may vary, but I am a simple person who prefers simple
solutions when having a general solution isn't required for the
problem I have. That is not to say that I wouldn't use a third party
library that provided such matrixes, just that I wouldn't go that
route myself unless I were developing such a library. :)

joe

Aug 15 '07 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: baruch | last post by:
Hello! I'm using PHP Version 4.3.3RC5-dev with GD Version bundled (2.0.15 compatible) to generated some graphics based on mysql data and to my surprise when I use the GD function imageline($im,...
16
by: Jacob | last post by:
It is common practice (I've heard) to always catch allocation exceptions from "new". How is done in practice? What would be a common procedure (path of sequence) after such an event has occured?...
6
by: Sandeep Chikkerur | last post by:
Hi, If the entire heap memory for dynamic allocation is not available, does the compiler always return NULL ? eg: char *s; s = (char *)malloc(...);
3
by: EasyKev | last post by:
We have been trying to upgrade all our C++ projects from VC6 to VS .Net2003 for a while (before VS 2005 arrived), and seem to be stuck now because of the performance degradation seen for the same...
38
by: Peteroid | last post by:
I looked at the addresses in an 'array<>' during debug and noticed that the addresses were contiguous. Is this guaranteed, or just something it does if it can? PS = VS C++.NET 2005 Express...
22
by: divya_rathore_ | last post by:
No pun intended in the subject :) Is dynamically allocated memory contiguous in C++? In C? Deails would be appreciated. warm regards, Divya Rathore (remove underscores for email ID)
22
by: Jack | last post by:
The following code can be compiled. But When I run it, it causes "Segmentation fault". int main(){ char **c1; *c1 = "HOW"; // LINE1 ++(*c1); *c1 = "ARE";
1
by: kingstonsmiler | last post by:
Hi, I want to allocate memory dynamically and the memory should be contiguous. My requirement is as follows for (n) { allocate memory dynamically of size 10; some processing;...
9
by: jmcgill | last post by:
Saw this used as an example. Compiles without warnings. "Works." Kosher or not? Why or why not? #include <stdio.h> int main(int argc, char **argv){ int i,j,k,l,m; int *p; i=2; j=4; k=8;...
5
by: Azaz ul haq | last post by:
Hello! What is meant by contiguous memory allocation in C++?
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
0
by: Aliciasmith | last post by:
In an age dominated by smartphones, having a mobile app for your business is no longer an option; it's a necessity. Whether you're a startup or an established enterprise, finding the right mobile app...
2
by: giovanniandrean | last post by:
The energy model is structured as follows and uses excel sheets to give input data: 1-Utility.py contains all the functions needed to calculate the variables and other minor things (mentions...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM) Please note that the UK and Europe revert to winter time on...
3
by: nia12 | last post by:
Hi there, I am very new to Access so apologies if any of this is obvious/not clear. I am creating a data collection tool for health care employees to complete. It consists of a number of...
0
isladogs
by: isladogs | last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, Mike...
4
by: GKJR | last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.