As I understand it, global variables are allocated in a memory area
outside of the stack and the heap. I know design-wise, global
variables should be avoided when possible. But are there any memory or
performance issues to consider when using global variables? Are there
any limits that aren't there when allocating on the stack?
In my case, I am making a large openGL application, and am finding
that I must keep lots of data in the global scope because the callback
function that draws the window doesn't take any parameters. I haven't
run into problems up to this point, and I try to keep the memory use
at a minimum by allocating only when the data is necessary and
deallocating when it's not needed any more, but it would surprise me
to find out that Quake 2 held all it's map data in global memory (or
maybe it shouldn't surprise me if it's not that big of a deal).
Thanks!
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
google
|
10/13/2003 4:26:27 AM |
|
Hi,
> As I understand it, global variables are allocated in a memory area
> outside of the stack and the heap. I know design-wise, global
> variables should be avoided when possible. But are there any memory or
> performance issues to consider when using global variables?
This very much depends on the architecture you're developing on. At
least, it is off-topic as far as C++ is concerned.
Memory issues: The memory required for the object is reserved before
main() is called, in a way that it is of no concern for C++. The
lifetime of the objects end as soon as the program ends, i.e. they
last *at least* until main() exits.
Performance issues: Depends on the platform. On the platforms I know
(i386 and co, Motorola 68K), it doesn't make a difference except possibly
for caching issues (i.e. placement of data such that it fits well into the
processor cache). Typically, the memory for these issues is part of the
program binary and gets allocated by the loader of the operating system.
Their constructors are called implicitly by the startup code of your binary,
and their destructors are called implicitly by the shut-down code.
> Are there
> any limits that aren't there when allocating on the stack?
The life time of the objects are different, namely it is global. Whether
this is a "limit" depends on your application.
So long,
Thomas
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Thomas
|
10/13/2003 8:40:48 PM
|
|
"axis" <google@luisma.com> wrote in message
> In my case, I am making a large openGL application, and am finding
> that I must keep lots of data in the global scope because the callback
> function that draws the window doesn't take any parameters. I haven't
> run into problems up to this point, and I try to keep the memory use
> at a minimum by allocating only when the data is necessary and
> deallocating when it's not needed any more, but it would surprise me
> to find out that Quake 2 held all it's map data in global memory (or
> maybe it shouldn't surprise me if it's not that big of a deal).
So you set some global variables, then call a function that takes no
arguments, and that function kind of takes arguments in the form of the
global variables, right? Will you program work correctly in a
multi-threaded environment?
Other than that, I can't think of any problem with the use of global
variables, but others may have better ideas.
--
+++++++++++
Siemel Naran
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Siemel
|
10/14/2003 4:12:47 PM
|
|
"axis" <google@luisma.com> wrote in message
news:eaf86cc1.0310121317.229101c0@posting.google.com...
> In my case, I am making a large openGL application, and am finding
> that I must keep lots of data in the global scope because the callback
> function that draws the window doesn't take any parameters.
Just a suggestion. To avoid cluttering the global space, you could keep
all your global data in a singleton class, see below.
-Michael.
================================================
#include <iostream>
class Global
{
public:
Global()
{
a = 1;
}
static Global& GetGlobal()
{
static Global global;
return global;
}
int a;
};
int main()
{
std::cout << "a=" << Global::GetGlobal().a << std::endl;
exit(0);
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Michael
|
10/14/2003 4:30:27 PM
|
|
> As I understand it, global variables are allocated in a memory area
> outside of the stack and the heap. I know design-wise, global
> variables should be avoided when possible. But are there any memory or
> performance issues to consider when using global variables?
Yes. By using global variables, you have poor data locality. If these
variables are simply passed to function calls, it doesn't make any
difference I guess. But global variables can always be aliased. They
are not local to a function. Therefore, if you refer to them in a
function for multiple calculations, they will probably have to be
refetched to cache each time they are accessed. In other words, avoid
globals if you use them for intensive calculations.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
spip_yeah
|
10/15/2003 10:41:12 AM
|
|
Doesn't it make more sense to use namespaces for this? The syntax
would certainly be cleaner. I don't see any benefits to using a
singleton unless you are using a compiler that doesn't comform well to
the standard.
- Niek
> [snip]
>
> Just a suggestion. To avoid cluttering the global space, you could keep
> all your global data in a singleton class, see below.
>
> -Michael.
>
> [snip]
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
njs8030
|
10/15/2003 10:42:30 AM
|
|
"Thomas Richter" <thor@cleopatra.math.tu-berlin.de> wrote in message
news:bme8ig$om3
> Memory issues: The memory required for the object is reserved before
> main() is called, in a way that it is of no concern for C++. The
> lifetime of the objects end as soon as the program ends, i.e. they
> last *at least* until main() exits.
The OP is using maps, vectors, and such which manage dynamic memory. The
sizeof vector includes just the start pointer, size, and capacity (a pointer
and two integers, or two pointers and one integer). Map is similar. The
memory actually used by the object is reserved at runtime.
--
+++++++++++
Siemel Naran
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Siemel
|
10/15/2003 10:46:46 AM
|
|
axis wrote:
> As I understand it, global variables are allocated in a memory area
> outside of the stack and the heap. I know design-wise, global
> variables should be avoided when possible. But are there any memory or
> performance issues to consider when using global variables? Are there
> any limits that aren't there when allocating on the stack?
The primiary issue to worry about is initialization/destruction order
dependencies. That is: correctness.
For performance, you may want to look at your program's memory access
patterns to see if you have locality-of-reference issues to worry
about (CPU cache, page faults), and whether using global variables
have any material effect on them. Here you have two dimensions to
analyze: call graphs and data access patterns, and their interactions.
As for limits: there are limits on static storage space, stack size,
and heap space, on most platforms. On embedded platforms (such as
PalmOS), these limits can be quite stringent. On general purpose
platforms, such as Win32/Linux/Unix, you usually get to use the
whole virtual address space. The stack is sometimes capped at
some static limit that can be modified with a linker option (Win32)
and/or operating environment parameters.
If your static storage exceeds some limit, usually the linker or
compiler will tell you; however, if your heap or stack exceeds the
limit, you'll have to discover that at runtime.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Antoun
|
10/15/2003 12:51:04 PM
|
|
In article <eaf86cc1.0310121317.229101c0@posting.google.com>, axis
wrote:
> As I understand it, global variables are allocated in a memory area
> outside of the stack and the heap. I know design-wise, global
> variables should be avoided when possible. But are there any memory or
> performance issues to consider when using global variables? Are there
> any limits that aren't there when allocating on the stack?
>
> In my case, I am making a large openGL application, and am finding
> that I must keep lots of data in the global scope because the callback
> function that draws the window doesn't take any parameters.
<snip>
I assume you're talking about GLUT?
Have a look at this C++ wrapper for it:
<http://www.duke.edu/~stetten/GlutMaster/GlutMaster.html>.
I don't see any licence terms on that, so you can't just go
copying that without asking. However, the key idea I saw in
it was to get an ID and use that as an index into an array of
pointers to an abstract class. There is apparently a
function called glutGetWindow() that returns an ID number for
the window currently being processed. So with the following
declarations:
class window {
public:
virtual /*result*/ foo(/*params*/);
virtual /*result*/ bar(/*params*/);
// ...
};
static const int MAX_WINDOWS = /* don't know */;
window * window_table[MAX_WINDOWS];
each of the callback functions can look like this:
/*result*/ foo(/*params*/)
{
return window_table[glutGetWindow()]->foo(/*params*/);
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Ben
|
10/15/2003 4:06:14 PM
|
|
In article <882fe461.0310141405.4a498943@posting.google.com>, spipyeah
<spip_yeah@yahoo.com> writes
> > As I understand it, global variables are allocated in a memory area
> > outside of the stack and the heap. I know design-wise, global
> > variables should be avoided when possible. But are there any memory or
> > performance issues to consider when using global variables?
>
>Yes. By using global variables, you have poor data locality. If these
>variables are simply passed to function calls, it doesn't make any
>difference I guess. But global variables can always be aliased. They
>are not local to a function. Therefore, if you refer to them in a
>function for multiple calculations, they will probably have to be
>refetched to cache each time they are accessed. In other words, avoid
>globals if you use them for intensive calculations.
Actually it is worse. Global variables are very bad news because of
aliasing. Any function that has a reference/pointer parameter which
could refer to a visible global variable and that uses global variable
in its definition must assume that aliasing is possible between the
(possibly dereferenced) parameter and the global variable. That
completely shoots a wide range of optimisation opportunities.
--
Francis Glassborow ACCU
If you are not using up-to-date virus protection you should not be reading
this. Viruses do not just hurt the infected but the whole community.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Francis
|
10/16/2003 2:02:55 PM
|
|
"spipyeah" <spip_yeah@yahoo.com> wrote in message
> Yes. By using global variables, you have poor data locality. If these
> variables are simply passed to function calls, it doesn't make any
> difference I guess. But global variables can always be aliased. They
> are not local to a function. Therefore, if you refer to them in a
> function for multiple calculations, they will probably have to be
> refetched to cache each time they are accessed. In other words, avoid
> globals if you use them for intensive calculations.
But the OP is using vectors and maps. Even if you declare these as
local or
member variables and pass them by const reference, you still have
aliasing
problems. It's only when you pass by value that you can get caching
optimizations due to lack of aliasing. We're unlikely to pass vector by
reference because it would be expensive, and also because the vector has
a
pointer to an array of elements and even if we receive a vector by value
the
pointer means that data access to these elements can probably not be
cached
anyway.
--
+++++++++++
Siemel Naran
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Siemel
|
10/16/2003 2:37:20 PM
|
|
njs8030@yahoo.com (NJS) wrote in message
news:<c57a219f.0310141437.4ec45ba0@posting.google.com>...
> > [snip]
> > Just a suggestion. To avoid cluttering the global space, you could
> > keep all your global data in a singleton class, see below.
> Doesn't it make more sense to use namespaces for this? The syntax
> would certainly be cleaner. I don't see any benefits to using a
> singleton unless you are using a compiler that doesn't comform well to
> the standard.
Controlling order of initialization, perhaps. The one time I did
something like this was before namespaces, but even then, the motivation
wasn't to avoid namespace pollution, but to control the order of
initialization.
--
James Kanze GABI Software mailto:kanze@gabi-soft.fr
Conseils en informatique orient�e objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
kanze
|
10/16/2003 2:40:36 PM
|
|
Hi,
spipyeah wrote:
> But global variables can always be aliased. They
> are not local to a function. Therefore, if you refer to them in a
> function for multiple calculations, they will probably have to be
> refetched to cache each time they are accessed.
Why?
int i;
void fun()
{
// some intensive calculations using i
}
There is no reason to refetch "i" every time it is used, IF fun() does
not call other functions as part of computations. On the other hand, IF
fun() does call other functions, then yes - the compiler cannot assume
that the other function does not change the value of "i" and it should
ensure that all functions operate on a single value.
Note that if fun() does not call other functions during calculations,
then the only aliasing can probably result from having multiple threads.
Even then, the compiler should be thread-agnostic by its own, because
even with refetching it cannot guarantee proper access synchronization.
> In other words, avoid
> globals if you use them for intensive calculations.
Depends on the structure of code used for calculations. If the code
operates only on global data, then there is no problem, because the
locality of reference can be as good as with local data.
Design issues aside, of course.
--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Maciej
|
10/16/2003 8:59:25 PM
|
|
> Why?
>
> int i;
> void fun()
> {
> // some intensive calculations using i
> }
>
> There is no reason to refetch "i" every time it is used, IF fun() does
> not call other functions as part of computations. On the other hand, IF
> fun() does call other functions, then yes - the compiler cannot assume
> that the other function does not change the value of "i" and it should
> ensure that all functions operate on a single value.
Ok, now take:
int i;
void fun( int *a )
{
do
{
// some stuff
i = a * something;
} while( go_on );
// some intensive calculations involving both i and (*a)
// among which:
}
a can potentially alias i, so because of the assignement to i, a has
to be refetched each iteration.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
spip_yeah
|
10/17/2003 11:43:39 AM
|
|
> But the OP is using vectors and maps.
You're right. I lost the scope of the discussion and talked about
globals and aliasing in general.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
spip_yeah
|
10/18/2003 10:08:36 AM
|
|
axis wrote:
> As I understand it, global variables are allocated in a memory area
> outside of the stack and the heap. I know design-wise, global
> variables should be avoided when possible. But are there any memory or
> performance issues to consider when using global variables? Are there
> any limits that aren't there when allocating on the stack?
On the architectures I know of, the performance of global variables is
very similar to the performance of automatic (stack) variables. The
difference usually isn't worth worrying about.
Global and static variables use their allocated memory throughout the
lifetime of the entire program. This is appropriate for variables that
are used throughout the entire program life, but it is wasteful for
variables with only a short active life.
In order to avoid global namespace pollution, consider using static
variables (or put them into the anonymous namespace) when you want the
lifetime of a global variable, but not the global visibility. Global
variables are usually criticised because of their visibility (and the
resulting lack of encapsulation and protection), not because of their
lifetime.
If your code has to behave well in the presence of multithreading, you
have to be aware that global/static variables exist only once in the
program, whereas each thread has its own stack. Global variables will
therefore require mutual exclusion mechanisms if they can be used by
multiple threads concurrently.
> In my case, I am making a large openGL application, and am finding
> that I must keep lots of data in the global scope because the callback
> function that draws the window doesn't take any parameters. I haven't
> run into problems up to this point, and I try to keep the memory use
> at a minimum by allocating only when the data is necessary and
> deallocating when it's not needed any more, but it would surprise me
> to find out that Quake 2 held all it's map data in global memory (or
> maybe it shouldn't surprise me if it's not that big of a deal).
I don't understand why data that needs to be accessible by the callback
function needs to be in the global scope. IIUC it would be sufficient if
the callback function had access to them, and that may well be possible
with static data, preferably even class static data.
For example, consider this:
template<typename Derived>
class Callback {
public:
typedef void (Function)();
virtual ~Callback() { that = 0; }
static void func() { assert(that); that->execute(); }
protected:
Callback() { assert(!that); that = this; }
private:
virtual void execute() =0;
static Callback<Derived>* that;
};
template<typename Derived> Callback<Derived>* Callback<Derived>::that=0;
Now, you can package your callback function with the data it needs:
class MyCallback : public Callback<MyCallback> {
void execute(); // implement your callback action here
// put whatever data members you need here.
};
The actual callback function that you hand over to the OpenGL system
would be MyCallback::func(). Note that callbacks created like this are
singletons: You can only have one object of a specific callback type.
Each callback class only allocates one pointer in global/static memory.
The memory for the actual data that is used by the callback function is
allocated with the MyCallback object in whatever way you like, so you
can restrict the lifetime as appropriate.
Cheers
Stefan
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Stefan
|
10/18/2003 1:40:33 PM
|
|
"Stefan Heinzmann" <stefan_heinzmann@yahoo.com> wrote in message
news:bme375$3hc$04
> If your code has to behave well in the presence of multithreading, you
> have to be aware that global/static variables exist only once in the
> program, whereas each thread has its own stack. Global variables will
> therefore require mutual exclusion mechanisms if they can be used by
> multiple threads concurrently.
I was just thinking, maybe we could replace the global variable with a
global array of variables, where the key of each element is the thread id,
and the value of each element is the original global variable. Something
like,
std::map<int, MyStruct> globalVar;
where MyStruct the OP's collection of vectors and maps. What problems might
we run into with this, other than clunky syntax? Everytime we want the
MyStruct we have to say globalVar[GetProcessId()].second.
Borland has a __thread keyword for this. Wish it were in the standard.
--
+++++++++++
Siemel Naran
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Siemel
|
10/19/2003 8:01:32 AM
|
|
"Siemel Naran" <SiemelNaran@REMOVE.att.net> wrote in
news:yyikb.6320$Ec1.575044@bgtnsc05-news.ops.worldnet.att.net:
> "Stefan Heinzmann" <stefan_heinzmann@yahoo.com> wrote in message
> news:bme375$3hc$04
>
> > If your code has to behave well in the presence of multithreading,
> > you have to be aware that global/static variables exist only once in
> > the program, whereas each thread has its own stack. Global variables
> > will therefore require mutual exclusion mechanisms if they can be
> > used by multiple threads concurrently.
>
> I was just thinking, maybe we could replace the global variable with a
> global array of variables, where the key of each element is the thread
> id, and the value of each element is the original global variable.
> Something like,
>
> std::map<int, MyStruct> globalVar;
>
> where MyStruct the OP's collection of vectors and maps. What problems
> might we run into with this, other than clunky syntax? Everytime we
> want the MyStruct we have to say globalVar[GetProcessId()].second.
This does not improve data safety for threaded applications.
If each element of your global array is reachable by all threads you
still have the problem of controlling multiple simultaneous access to
that data from two or more threads. You have not eliminated the need for
mutual exclusion mechanisms. You have only added verbosity to the syntax.
The simple truth is that any data shared between threads needs to be
protected using mutual exclusion mechanisms. Failure to do so results
in unacceptable race conditions.
Mutual exclusion mechanisms always involve some amount of processing
overhead. They force some synchronization onto what are otherwise
asynchronous threads. There is a strong likelihood of deadlock if a
set of threads needs to simultaneously access a common set of shared
data where the number of mutual exclusion locks is greater than 1.
Race conditions and deadlocks are two reasons multi-threaded applications
are much more complex to design than single-threaded applications.
Jim Rogers
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
James
|
10/19/2003 4:15:35 PM
|
|
Siemel Naran wrote:
> [snip]
> Borland has a __thread keyword for this. Wish it were in the standard.
Also, Microsoft has thread local storage (forgot the keyword).
Implementation-wise, I believe the thread-local storage is
allocated from the heap, along with the other resources for
the thread.
Anyway, thread-local storage is not the same as global
storage. Global storage is pre-allocated at compile-time
(per translation unit), and consolidated at link-time.
On the other hand, thread-local storage is only measured
statically; allocation takes place when threads are created
at runtime.
Since we're talking C++, we have to accepts that some parts
of the static storage space are initialized at runtime.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Antoun
|
10/19/2003 6:38:43 PM
|
|
Siemel Naran wrote:
> "Stefan Heinzmann" <stefan_heinzmann@yahoo.com> wrote in message
> news:bme375$3hc$04
>
> > If your code has to behave well in the presence of multithreading, you
> > have to be aware that global/static variables exist only once in the
> > program, whereas each thread has its own stack. Global variables will
> > therefore require mutual exclusion mechanisms if they can be used by
> > multiple threads concurrently.
>
> I was just thinking, maybe we could replace the global variable with a
> global array of variables, where the key of each element is the thread id,
> and the value of each element is the original global variable. Something
> like,
>
> std::map<int, MyStruct> globalVar;
>
> where MyStruct the OP's collection of vectors and maps. What problems might
> we run into with this, other than clunky syntax? Everytime we want the
> MyStruct we have to say globalVar[GetProcessId()].second.
Thread libraries often offer thread-specific data (pthreads) or
thread-local storage (Win32) to address this. Your map-based solution is
another valid solution, and it probably is portable as far as thread ids
are portable (You may have to wrap them into a compatibility class).
For small data items, map is a fairly inefficient container (regarding
memory consumption). You might want to consider if a std::vector better
serves your needs. My first assumption would be that insertions and
deletions happen much less frequently than lookups, so keeping the
vector sorted and doing the lookup using a binary search might be a good
idea.
It might also be useful to wrap the general idea into something that can
utilize support from the threading facilities of the underlying system
if they are available. This could be a lot more efficient.
Note that the lifetime of the thread-specific global variable would be
the same as the lifetime of the thread, or more specifically the
thread's stack. The variable could thus be an automatic variable
allocated by the thread function before it does the "real" work. The
problem is then reduced to providing access to this without having to
pass it on as a function argument. So it would suffice to store a
pointer to MyStruct in our vector.
> Borland has a __thread keyword for this. Wish it were in the standard.
It would require threads to be standardized. That would be useful, but
it definitely is non-trivial.
Cheers
Stefan
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Stefan
|
10/19/2003 7:25:55 PM
|
|
"James Rogers" <jimmaureenrogers@att.net> wrote in message
> "Siemel Naran" <SiemelNaran@REMOVE.att.net> wrote in
> > std::map<int, MyStruct> globalVar;
> >
> > where MyStruct the OP's collection of vectors and maps. What problems
> > might we run into with this, other than clunky syntax? Everytime we
> > want the MyStruct we have to say globalVar[GetProcessId()].second.
>
> This does not improve data safety for threaded applications.
> If each element of your global array is reachable by all threads you
> still have the problem of controlling multiple simultaneous access to
> that data from two or more threads. You have not eliminated the need for
> mutual exclusion mechanisms. You have only added verbosity to the syntax.
I was hoping the programmer would be well behaved and only access the
variables in their thread. We can enforce this with encapsulation.
class GetGlobalVar {
public:
static MyStruct& getVariable();
private:
static std::map<int, MyStruct> threadVariables;
};
MyStruct& GetGlobalVar::getVariable() {
return threadVariables[GetProcessId()]; // may insert new node
}
Anyway, is it conceivable that (the common) implementation of
std::map::operator[] or std::map::insert could render it unsafe for use in
multi-threading? What if one thread tries to insert a new node, and the
implementation implements maps through balanced red-black trees? I've never
written a red-black tree, but here's my thinking: While the implementation
is balancing the red-black tree by changing the parent, left-child, and
right-child pointers of the nodes, the tree is not in a usable state. So
another thread ought not to even access the tree, let alone create a new
node. Is this correct?
So in that case we can replace
static std::map<int, MyStruct> threadVariables;
with
static MyStruct[MAX_NUM_THREADS] threadVariables;
--
+++++++++++
Siemel Naran
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Siemel
|
10/20/2003 9:13:14 PM
|
|
Hi,
spipyeah wrote:
> Ok, now take:
>
> int i;
> void fun( int *a )
> {
> do
> {
> // some stuff
>
> i = a * something;
I assume dereferencing a here.
> } while( go_on );
> a can potentially alias i, so because of the assignement to i, a has
> to be refetched each iteration.
I understand your point and you're right here.
But the code above does not really show that global data is a source of
aliasing problems, but rather that it is the algorithm's design issue.
In other words, a valid algorithm working on the local data can be
always restated in terms of globals, without introducing any aliasing,
having in mind what I wrote in my previous post. In the other direction,
the code exposing aliasing problems (like the one above) cannot be
easily restate in terms of only local data without substantial changes
in the design. So - it is the code that is faulty, not the bare fact
that global data is used.
That's why I see no problem with globals, when performance and locality
of reference are discussed. For example, sorting an array is the same
performance problem, no matter where the array is located, and no
aliasing may be introduced in the sorting algorithm by the bare fact
that you move your array from local to the global space.
Of course, we have to rule out issues like different pointer sizes
(vide: near/far pointers in 16-bit x86 systems) for different segments
and related stuff, if the whole discussion has to have any sense - with
such issues, we're no longer in the realms of standard C++.
--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Maciej
|
10/20/2003 9:19:02 PM
|
|
"Stefan Heinzmann" <stefan_heinzmann@yahoo.com> wrote in message
> For small data items, map is a fairly inefficient container (regarding
> memory consumption). You might want to consider if a std::vector better
> serves your needs. My first assumption would be that insertions and
> deletions happen much less frequently than lookups, so keeping the
> vector sorted and doing the lookup using a binary search might be a good
> idea.
Yes, a sorted vector usually outperforms map.
> It might also be useful to wrap the general idea into something that can
> utilize support from the threading facilities of the underlying system
> if they are available. This could be a lot more efficient.
What are you talking about?
> Note that the lifetime of the thread-specific global variable would be
> the same as the lifetime of the thread, or more specifically the
> thread's stack. The variable could thus be an automatic variable
> allocated by the thread function before it does the "real" work. The
> problem is then reduced to providing access to this without having to
> pass it on as a function argument. So it would suffice to store a
> pointer to MyStruct in our vector.
A problem with my map solution is that the variable is not removed when the
thread is destroyed. It may not be harmful though.
Also, because the map allocates dynamic memory and sets pointers, it may not
be safe. See my response to Jim.
> > Borland has a __thread keyword for this. Wish it were in the standard.
>
> It would require threads to be standardized. That would be useful, but
> it definitely is non-trivial.
And far into the future...
--
+++++++++++
Siemel Naran
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Siemel
|
10/21/2003 3:44:06 PM
|
|
Siemel Naran wrote:
> "Stefan Heinzmann" <stefan_heinzmann@yahoo.com> wrote in message
[...]
>>It might also be useful to wrap the general idea into something that can
>> utilize support from the threading facilities of the underlying system
>>if they are available. This could be a lot more efficient.
>
>
> What are you talking about?
Instead of using a map or vector to store the thread-specific globals
directly, I was proposing to use the thread-local variables provided by
the operating system or the threading library (such as the Win32 TLS or
the pthreads thread-specific data functions), if they're there. Maybe it
is possible to hide these system-specifics in a portable wrapper class.
[...]
Cheers
Stefan
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Stefan
|
10/22/2003 3:57:29 PM
|
|
In article <bn49rd$76k$00$1@news.t-online.com>, Stefan Heinzmann wrote:
> Siemel Naran wrote:
>> "Stefan Heinzmann" <stefan_heinzmann@yahoo.com> wrote in message
> [...]
>>>It might also be useful to wrap the general idea into something that can
>>> utilize support from the threading facilities of the underlying system
>>>if they are available. This could be a lot more efficient.
>>
>>
>> What are you talking about?
>
> Instead of using a map or vector to store the thread-specific globals
> directly, I was proposing to use the thread-local variables provided by
> the operating system or the threading library (such as the Win32 TLS or
> the pthreads thread-specific data functions), if they're there. Maybe it
> is possible to hide these system-specifics in a portable wrapper class.
Boost.Threads supports TLS, although there it's called thread-*specific*
storage instead.
Using a map or vector for thread-specific storage is horribly inefficient
in terms of both programmer and computer time. Access to it typically
needs to be synchronised, possibly resulting in a bottleneck. In any
case not all thread APIs provide an ordering relation on thread IDs.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Ben
|
10/22/2003 6:42:13 PM
|
|
Ben Hutchings wrote:
[... thread-specific storage ...]
> In any case not all thread APIs provide an ordering relation on
> thread IDs.
Oh yeah.
<quote>
Not having been around for prior proposals regarding
pthread_hash() or pthread_compare(), I would assume that
"use pthread_key_create() and pthread_[gs]etspecific()"
would be the argument against adding fluff into the spec...
</quote>
Funny, oder? ;-) More info on this: <http://tinyurl.com/buj9>
(Subject: pthread_compare() and pthread_hash()).
regards,
alexander.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
0
|
|
|
|
Reply
|
Alexander
|
10/23/2003 11:24:37 AM
|
|
|
25 Replies
139 Views
(page loaded in 0.357 seconds)
Similiar Articles: Global Variable vs Struct Variable Question - comp.lang.asm.x86 ...It makes sense that global variable has its own memory address ... or class can slow and degrade the performance on Pentium IV. It is preferable to use global ... Pointers to global and stack variables - comp.compilersStruct / Class Performance? - comp.lang.asm.x86 I have gathered time data for global variables ... where pointers and global variables in C are saved in memory, in ... How can we define global but constant variable? - comp.soft-sys ...struct/union difference - comp.lang.c++.moderated... the variables (on the stack or in global memory)? There isn't any difference that I can see, so ... Allocating Memory in DOS - comp.lang.asm.x86... not via cmd ... comp.lang ... gggrrr, I'm low on memory once again with good old PC DOS 2000 ... comp.unix.solaris - page 447 Regarding global variables memory allocation ... /bin/sh: Local variables in a function ? - comp.unix.solaris ...But my underlying motivation to make it local was merely from a memory and ... In shell a global variable would be one that can be seen by the process children (sub ... struct/union difference - comp.lang.c++.moderatedSo, the question is, what would the difference be between an anonymous, untagged struct and just declaring the variables (on the stack or in global memory)? Poker hand evaluator - comp.lang.javascript... clarity, and perhaps from the point of view of performance ... pass it as a parameter, you could save a lot of memory grinding. (Or, you could have it in a global variable ... Down-cast a polymorphic pointer? - comp.lang.fortran... multiple interfaces must be declared, and it might be more economic to use a set of procedure pointers cproc_1, cproc_2, ... which are declared as global variables. Clear all except some? - comp.soft-sys.matlabClear variables from memory - MATLAB - MathWorks - MATLAB and ... clearvars a* -except ab. Clear all global variables except those starting with x: clearvars -global ... STL allocators, global new/delete using the heap and shared memory ...They prefer that global new gets memory from the heap so that they can get memory from the ... They seem to think the problem is solved by declaring the STL variable with a ... CS, DS, and SS Segments Together? - comp.lang.asm.x86On Windows, I believe the global/local legacy memory functions ... the CRT uses a thread-local heap for performance ... under MASM 6.14 so I can write >global variables by ... converting C/Visual BASIC code to MATLAB - comp.soft-sys.matlab ...No storage allocated, no data types, just text that gets put in to the source. ... MATLAB _does_ have global variables, but they have to be declared as global in every ... Copy-on-write for real/imaginary parts of complex data? - comp ...... data copy of the input off to the side (e.g., in a global variable ... forever and the memory gets leaked since the second variable knows nothing about this memory. FM8 Script Variable - comp.databases.filemaker... it doesn't) BTW I understand the difference between global and local variables. ... But the script is aborting with message: Out of memory! ... Using the binded variables, do ... External variables - comp.lang.asm.x86I have an asm file containing a global data label, eg ... If you put the address of something in a variable type ... A pointer is (typically) a 32-bit area of storage that ... Using Local and Global Variables Carefully - LabVIEW 2010 Help ...If you read from the global variable in several places in an application, you create several memory buffers, which is inefficient and slows performance. Performance variables - IBM DB2 9.7 for Linux, UNIX, and Windows... higher value for this registry variable is wasted memory if ... This mode allows the global query cache ... This variable enables a performance enhancement known as "rollout" ... 7/14/2012 8:59:05 PM
|