Discussion:
loop vs memset to initialize array.. different results?
(too old to reply)
silversurfer2025
2006-07-27 14:21:25 UTC
Permalink
Hello everybdy,
I am a little confused for the following reason:

In my code I used a simple for-loop in order to initialize a 2D-array
of floats to zero. Because of efficiency reasons, I changed it to use
memset and I get totally different results.. How can this be?

Here is the example:

float gaborfilter[filtersize][filtersize];

memset(gaborfilter, 0, sizeof(float) * filtersize * filtersize);

OR

for(int i = 0; i < filtersize;i++){
for(int j = 0; j < filtersize;j++){
gaborfilter[i][j] = 0;
}
}

Later calculations give totally different results using these two
methods. Is there something really obviously different, which I am
currently missing?

Thanks a lot
Tim
Victor Bazarov
2006-07-27 14:25:50 UTC
Permalink
Post by silversurfer2025
Hello everybdy,
In my code I used a simple for-loop in order to initialize a 2D-array
of floats to zero. Because of efficiency reasons, I changed it to use
memset and I get totally different results.. How can this be?
float gaborfilter[filtersize][filtersize];
memset(gaborfilter, 0, sizeof(float) * filtersize * filtersize);
OR
for(int i = 0; i < filtersize;i++){
for(int j = 0; j < filtersize;j++){
gaborfilter[i][j] = 0;
}
}
Later calculations give totally different results using these two
methods. Is there something really obviously different, which I am
currently missing?
A "zero" in a floating point variable is not necessarily the same as
"all bits zero". 'memset' clears all bits. Assigning 0 to the elements
of the array does THE RIGHT THING(tm). Have you thought about simply
initialising the array or do you need to periodically clear it?

float blah[one][two] = {}; // sets all elements to 0

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Mike Wahler
2006-07-27 14:33:51 UTC
Permalink
Post by silversurfer2025
Hello everybdy,
In my code I used a simple for-loop in order to initialize a 2D-array
of floats to zero. Because of efficiency reasons,
Have you proven with timing or profiling that there
is indeed an efficiency problem?
Post by silversurfer2025
I changed it to use
memset
Don't.
Post by silversurfer2025
and I get totally different results.. How can this be?
Because the representation of 0.0 isn't necessarily
all-bits-zero.
Post by silversurfer2025
float gaborfilter[filtersize][filtersize];
memset(gaborfilter, 0, sizeof(float) * filtersize * filtersize);
This is only guaranteed to work with unsigned integer types
(e.g. 'unsigned int', 'unsigned char'.
Post by silversurfer2025
OR
for(int i = 0; i < filtersize;i++){
for(int j = 0; j < filtersize;j++){
gaborfilter[i][j] = 0;
This is the only portable way to assign values to
each element of the array of type 'float' objects.


But if you want all values to be zero, you could simply
initialize the array when you create it:

float gaborfilter[filtersize][filtersize] = {0};
/* (all elements now have value of zero) */
Post by silversurfer2025
}
}
Later calculations give totally different results using these two
methods. Is there something really obviously different, which I am
currently missing?
See above.

Also, you should use type 'double' rather than 'float'.
There's even a possibility that type 'double' could be
more 'efficient' (but this ultimately depends upon your
platforrm).

And finally, this is C++, so imo you should be using
containers rather than arrays.

std::vector<float>(filtersize, std::vector<float>(filtersize));

/* All elements now have values of zero. */

-Mike
silversurfer2025
2006-07-27 14:43:31 UTC
Permalink
Post by Mike Wahler
Post by silversurfer2025
Hello everybdy,
In my code I used a simple for-loop in order to initialize a 2D-array
of floats to zero. Because of efficiency reasons,
Have you proven with timing or profiling that there
is indeed an efficiency problem?
Post by silversurfer2025
I changed it to use
memset
Don't.
OK ;)
Post by Mike Wahler
Post by silversurfer2025
and I get totally different results.. How can this be?
Because the representation of 0.0 isn't necessarily
all-bits-zero.
Post by silversurfer2025
float gaborfilter[filtersize][filtersize];
memset(gaborfilter, 0, sizeof(float) * filtersize * filtersize);
This is only guaranteed to work with unsigned integer types
(e.g. 'unsigned int', 'unsigned char'.
Ah, ok.. wat a pitty... I thought that I could get my code to work
faster..
Post by Mike Wahler
Post by silversurfer2025
OR
for(int i = 0; i < filtersize;i++){
for(int j = 0; j < filtersize;j++){
gaborfilter[i][j] = 0;
This is the only portable way to assign values to
each element of the array of type 'float' objects.
But if you want all values to be zero, you could simply
float gaborfilter[filtersize][filtersize] = {0};
I tried this one before, but I get the compiler error:
error: variable-sized object 'gaborfilter' may not be
initialized
Anything I can do about it?
Post by Mike Wahler
/* (all elements now have value of zero) */
Post by silversurfer2025
}
}
Later calculations give totally different results using these two
methods. Is there something really obviously different, which I am
currently missing?
See above.
Also, you should use type 'double' rather than 'float'.
There's even a possibility that type 'double' could be
more 'efficient' (but this ultimately depends upon your
platforrm).
I'll change it right away, I thought that float would be better for
memory-reasons..
Post by Mike Wahler
And finally, this is C++, so imo you should be using
containers rather than arrays.
I am only using them for calculations, the results are later put into a
vector. (please do not ask!)
Post by Mike Wahler
std::vector<float>(filtersize, std::vector<float>(filtersize));
/* All elements now have values of zero. */
-Mike
Tim
Victor Bazarov
2006-07-27 14:54:20 UTC
Permalink
Post by silversurfer2025
Post by Mike Wahler
[..]
But if you want all values to be zero, you could simply
float gaborfilter[filtersize][filtersize] = {0};
error: variable-sized object 'gaborfilter' may not be
initialized
Anything I can do about it?
Variable-sized object? Are you using g++ extensions? You might want
to consider a dynamic array then...
Post by silversurfer2025
[..]
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
silversurfer2025
2006-07-27 15:05:11 UTC
Permalink
Post by Victor Bazarov
Post by silversurfer2025
Post by Mike Wahler
[..]
But if you want all values to be zero, you could simply
float gaborfilter[filtersize][filtersize] = {0};
error: variable-sized object 'gaborfilter' may not be
initialized
Anything I can do about it?
Variable-sized object? Are you using g++ extensions? You might want
to consider a dynamic array then...
Hm.. I do not even know what these extensions are. I do compile with
g++ but the declaration I gave above is all I wrote. I guess it says
dynamic because there is a variable (filtersize) giving the length of
the array which should be created?

Thanks once more
Tim
Post by Victor Bazarov
Post by silversurfer2025
[..]
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Mike Wahler
2006-07-27 15:02:33 UTC
Permalink
Post by silversurfer2025
Post by Mike Wahler
Post by silversurfer2025
Hello everybdy,
In my code I used a simple for-loop in order to initialize a 2D-array
of floats to zero. Because of efficiency reasons,
Have you proven with timing or profiling that there
is indeed an efficiency problem?
Post by silversurfer2025
I changed it to use
memset
Don't.
OK ;)
Post by Mike Wahler
Post by silversurfer2025
and I get totally different results.. How can this be?
Because the representation of 0.0 isn't necessarily
all-bits-zero.
Post by silversurfer2025
float gaborfilter[filtersize][filtersize];
memset(gaborfilter, 0, sizeof(float) * filtersize * filtersize);
This is only guaranteed to work with unsigned integer types
(e.g. 'unsigned int', 'unsigned char'.
Ah, ok.. wat a pitty... I thought that I could get my code to work
faster..
Have you proven that it's not fast enough?
Post by silversurfer2025
Post by Mike Wahler
Post by silversurfer2025
OR
for(int i = 0; i < filtersize;i++){
for(int j = 0; j < filtersize;j++){
gaborfilter[i][j] = 0;
This is the only portable way to assign values to
each element of the array of type 'float' objects.
But if you want all values to be zero, you could simply
float gaborfilter[filtersize][filtersize] = {0};
error: variable-sized object 'gaborfilter' may not be
initialized
Anything I can do about it?
Yes. Don't use non-const expressions to specify array
dimensions. They're not allowed in C++. Either use
a literal constant, a const-qualified object, or a macro:

float gaborfilter[10][10];

or

const size_t filtersize(10);
float gaborfilter[filtersize][filtersize];

or

#define filtersize 10

float gaborfilter[filtersize][filtersize];

But as I've pointed out already, a container (e.g.
vector) would be better.
Post by silversurfer2025
Post by Mike Wahler
/* (all elements now have value of zero) */
Post by silversurfer2025
}
}
Later calculations give totally different results using these two
methods. Is there something really obviously different, which I am
currently missing?
See above.
Also, you should use type 'double' rather than 'float'.
There's even a possibility that type 'double' could be
more 'efficient' (but this ultimately depends upon your
platforrm).
I'll change it right away, I thought that float would be better for
memory-reasons..
Stop guessing. :-) Prove there's a problem before trying to solve it.

-Mike
Andrey Tarasevich
2006-07-27 17:03:12 UTC
Permalink
Post by Mike Wahler
Post by silversurfer2025
float gaborfilter[filtersize][filtersize];
memset(gaborfilter, 0, sizeof(float) * filtersize * filtersize);
This is only guaranteed to work with unsigned integer types
(e.g. 'unsigned int', 'unsigned char'.
...
Strictly speaking, this is only guaranteed to work with 'char' types (signed and
unsigned). It is not guaranteed to work with larger integral types because it
might set their padding bits (if any) incorrectly.

There's a C99 proposal to require it to work with all integral types (I don't
know its current status).

--
Best regards,
Andrey Tarasevich
Pete Becker
2006-07-27 17:59:50 UTC
Permalink
Post by Andrey Tarasevich
Strictly speaking, this is only guaranteed to work with 'char' types (signed and
unsigned). It is not guaranteed to work with larger integral types because it
might set their padding bits (if any) incorrectly.
To underscore the "strictly speaking" portion: this works just fine with
every floating-point implementation I've used. The problem is
undoubtedly somewhere else, despite the apparent certainty expressed in
most of the answers.
Howard
2006-07-27 18:31:56 UTC
Permalink
Post by silversurfer2025
Hello everybdy,
In my code I used a simple for-loop in order to initialize a 2D-array
of floats to zero. Because of efficiency reasons, I changed it to use
memset and I get totally different results.. How can this be?
float gaborfilter[filtersize][filtersize];
memset(gaborfilter, 0, sizeof(float) * filtersize * filtersize);
OR
for(int i = 0; i < filtersize;i++){
for(int j = 0; j < filtersize;j++){
gaborfilter[i][j] = 0;
}
}
Later calculations give totally different results using these two
methods. Is there something really obviously different, which I am
currently missing?
What differs in the results? And how do you know (for sure) that it's
related to the initialization above and not some other code that's run
later?

-Howard
silversurfer2025
2006-07-28 09:15:09 UTC
Permalink
Post by Howard
Post by silversurfer2025
Hello everybdy,
In my code I used a simple for-loop in order to initialize a 2D-array
of floats to zero. Because of efficiency reasons, I changed it to use
memset and I get totally different results.. How can this be?
float gaborfilter[filtersize][filtersize];
memset(gaborfilter, 0, sizeof(float) * filtersize * filtersize);
OR
for(int i = 0; i < filtersize;i++){
for(int j = 0; j < filtersize;j++){
gaborfilter[i][j] = 0;
}
}
Later calculations give totally different results using these two
methods. Is there something really obviously different, which I am
currently missing?
What differs in the results? And how do you know (for sure) that it's
related to the initialization above and not some other code that's run
later?
Thanks for this little hint! I was totally sure that it had to be
initialization-dependent because after I changed the for loop to a call
to memset, the results of a calculation differed.

Now comes the (for me) heavy part: I have to admit that there seems to
be no difference. I found out that I had a memory-access error
somewhere else such that another variable which was as well used in the
calculations had either one or the other phantasy-value.. Funnily
enough, the one value appeared when using the for loop and the other
when using memset (even after reboots, etc).
For now, all I can say is:
- Thanks everybody for your help, it is appreciated very much!
- Thanks to this thread I found another even more severe error in the
code
- It seems as if there is no difference (at least not for me) when
using memset or a for loop...

Now to come back to the main issue: Is it guaranteed to work with
memset or am I once more only currently lucky and it might and might
not work in some situations?

Thanks once more for your hel
Tim
Post by Howard
-Howard
Jerry Coffin
2006-07-28 16:27:13 UTC
Permalink
In article <***@p79g2000cwp.googlegroups.com>,
***@web.de says...

[ ... initializing an array of float to 0 ]
Post by silversurfer2025
Now to come back to the main issue: Is it guaranteed to work with
memset or am I once more only currently lucky and it might and might
not work in some situations?
In theory, it's not guaranteed to work with every possible
implementation of float. In reality, I'm _reasonably_ certain there's
no implementation of float for which it won't work. In the usual
case, floating point numbers only need a small subset of the bits set
to zero for the number overall to have the value zero -- if these
bits are zero, the rest of the bits are ignored.

As I said above, _in theory_ an implementation for which memset would
cause a problem -- but I've never heard of one for which it was the
case, and I'm somewhat doubtful that it'll happen anytime soon
either.

Personally, I'd tend to avoid using memset anyway. It only really
works with the value 0 -- any other input value can produce
unexpected results.
--
Later,
Jerry.

The universe is a figment of its own imagination.
Frederick Gotham
2006-07-28 16:40:54 UTC
Permalink
Post by Jerry Coffin
Personally, I'd tend to avoid using memset anyway. It only really
works with the value 0 -- any other input value can produce
unexpected results.
Set the first five characters of a string to asterisks:

memset(str,'*',5);

Perfectly safe.
--
Frederick Gotham
Jerry Coffin
2006-07-28 17:09:55 UTC
Permalink
In article <q6ryg.11962$***@news.indigo.ie>, ***@SPAM.com
says...
Post by Frederick Gotham
Post by Jerry Coffin
Personally, I'd tend to avoid using memset anyway. It only really
works with the value 0 -- any other input value can produce
unexpected results.
memset(str,'*',5);
Perfectly safe.
That depends on what you mean by 'string' -- if I do something like:

std::string str;

memset(str, '*', 5);

then no, it's not safe (though it's barely possible it'll work, if
the string in question has SSO, and puts the buffer first, which is
semi-common to make debugging easier...)

We both know you're taking the statement out of context in any case:
I was talking about using memset on _float_ variables -- and for
them, the only value that will normally produce useful results is 0.
--
Later,
Jerry.

The universe is a figment of its own imagination.
Frederick Gotham
2006-07-28 19:48:39 UTC
Permalink
Post by Jerry Coffin
Post by Frederick Gotham
memset(str,'*',5);
Perfectly safe.
std::string str;
memset(str, '*', 5);
then no, it's not safe (though it's barely possible it'll work, if
the string in question has SSO, and puts the buffer first, which is
semi-common to make debugging easier...)
I was referring to homemade, null-terminated, char buffer strings:

char str[] = "Hello, I drive a car.";

memset(str,'*',5);
Post by Jerry Coffin
I was talking about using memset on _float_ variables -- and for
them, the only value that will normally produce useful results is 0.
Please define "normally". If you mean, "on a lot of systems", then yes, go
ahead and use memset to set it to zero.

However, the Standard imposes no restriction upon the implementation
whereby the zero value for a float must be represented as all bits zero in
memory.
--
Frederick Gotham
Jerry Coffin
2006-07-28 20:55:12 UTC
Permalink
In article <rStyg.11969$***@news.indigo.ie>, ***@SPAM.com
says...

[ ... ]
Post by Frederick Gotham
Post by Jerry Coffin
I was talking about using memset on _float_ variables -- and for
them, the only value that will normally produce useful results is 0.
Please define "normally". If you mean, "on a lot of systems", then yes, go
ahead and use memset to set it to zero.
However, the Standard imposes no restriction upon the implementation
whereby the zero value for a float must be represented as all bits zero in
memory.
Gosh, you say that almost as if it wasn't virtually a direct copy of
what I said in the post you started out by following up to.

The reality is that it's a bit better than you're implying though --
while it's true that the C++ standard doesn't make such a
requirement, it's also true that not only "on a lot of systems", but
in fact for every floating point format of which I'm aware, all bits
set to 0 does give the value 0.0. That's somewhat different from the
rule you noted above though -- in particular, many (perhaps most)
allow some bits to be set and STILL give a value of 0.0.

This rule also includes all of the other floating point formats I
know of, including things as diverse as the VAX G-format, CDC
mainframes, and early Crays (all of which pre-dated the IEEE
standard). To make a long story short, unless somebody decides to
invent a new format and sets out with the specific intent of breaking
it, there's almost no chance you'll ever run into something in which
all bits zero in a floating point number will give a value of 0.0.
--
Later,
Jerry.

The universe is a figment of its own imagination.
Jerry Coffin
2006-07-28 20:59:48 UTC
Permalink
In article <***@news.sunsite.dk>,
***@taeus.com says...

[ ... ]
Post by Jerry Coffin
there's almost no chance you'll ever run into something in which
all bits zero in a floating point number will give a value of 0.0.
Oops -- of course that should read "other than 0.0."
--
Later,
Jerry.

The universe is a figment of its own imagination.
Frederick Gotham
2006-07-29 03:38:43 UTC
Permalink
Post by Jerry Coffin
To make a long story short, unless somebody decides to
invent a new format and sets out with the specific intent of breaking
it, there's almost no chance you'll ever run into something in which
all bits zero in a floating point number will give a value other than 0.0.
Perhaps you should propose that the Standards Committee impose such a
restriction.

(I'm not being sarcastic.)
--
Frederick Gotham
Jerry Coffin
2006-07-29 14:42:00 UTC
Permalink
In article <7LAyg.11977$***@news.indigo.ie>, ***@SPAM.com
says...
Post by Frederick Gotham
Post by Jerry Coffin
To make a long story short, unless somebody decides to
invent a new format and sets out with the specific intent of breaking
it, there's almost no chance you'll ever run into something in which
all bits zero in a floating point number will give a value other than 0.0.
Perhaps you should propose that the Standards Committee impose such a
restriction.
I'd rather see the committee spend its time on things I think would
accomplish more.

If I was going to suggest anything, it would be that "initializing"
things to 0/0.0/null pointer is common enough that it might be worth
adding a standard algorithm specifically for that purpose.

In this case, the (unsupported) claim was that using memset would
improve performance. Personally, I doubt that it really did/does/will
given any substantial performance improvement. If, however, you could
do a lot better than a loop for some types, it would be relatively
easy for the library author to provide a specialization for it.

The result would be code that's cleaner and easier to read, while
providing the same benefit -- and potentially providing a lot more
benefit in the future. Just for example, I can fairly easily imagine
a library that provided multi-threaded versions of some algorithms to
improve speed not only by percentages, but by multiples.
--
Later,
Jerry.

The universe is a figment of its own imagination.
Frederick Gotham
2006-07-29 16:42:30 UTC
Permalink
Post by Jerry Coffin
If I was going to suggest anything, it would be that "initializing"
things to 0/0.0/null pointer is common enough that it might be worth
adding a standard algorithm specifically for that purpose.
SomePOD array[12] = {};
--
Frederick Gotham
Jerry Coffin
2006-07-29 19:53:00 UTC
Permalink
In article <WdMyg.12011$***@news.indigo.ie>, ***@SPAM.com
says...
Post by Frederick Gotham
Post by Jerry Coffin
If I was going to suggest anything, it would be that "initializing"
things to 0/0.0/null pointer is common enough that it might be worth
adding a standard algorithm specifically for that purpose.
SomePOD array[12] = {};
Note that I put "initializing" in quotes. That was meant to suggest a
situation where we want behavior a lot like initializing, but real
initialization won't work, or would be clumsy, inefficient, etc.
--
Later,
Jerry.

The universe is a figment of its own imagination.
Frederick Gotham
2006-07-29 20:11:05 UTC
Permalink
Post by Jerry Coffin
says...
Post by Frederick Gotham
Post by Jerry Coffin
If I was going to suggest anything, it would be that "initializing"
things to 0/0.0/null pointer is common enough that it might be worth
adding a standard algorithm specifically for that purpose.
SomePOD array[12] = {};
Note that I put "initializing" in quotes. That was meant to suggest a
situation where we want behavior a lot like initializing, but real
initialization won't work, or would be clumsy, inefficient, etc.
Forgive me to play devil's advocate... but could you give an example of
where initialisation wouldn't work, or where it would be clumsy or
inefficient?

If anything, we could have a template function as follows:

#include <cstddef>
#include <new>

template<class T,std::size_t len>
void InitArray(T (&arr)[len])
{
T const *const p_over = arr + len;

T *p = arr;

do ::new(p++) T();
while(p != p_over);
}
--
Frederick Gotham
Jerry Coffin
2006-07-29 21:04:17 UTC
Permalink
In article <thPyg.12031$***@news.indigo.ie>, ***@SPAM.com
says...

[ ... ]
Post by Frederick Gotham
Forgive me to play devil's advocate... but could you give an example of
where initialisation wouldn't work, or where it would be clumsy or
inefficient?
Sure -- an object that's slow to construct, but much faster to zero
out, so (for example) in a loop, you would greatly prefer to zero it
out at each iteration rather than create it anew. For a concrete
example, I (long ago, so I'll admit I don't remember all the details)
wrote some code that dealt with dial-up networking. For better or
worse, the top-level object represented both a dial-up connection and
one or more connections to servers. You could "re-initialize" it, so
it forgot about existing connections to servers, but when/if you
destroyed the object, it hung up the phone. Creating a new object re-
dialed the phone.

As such, re-initializing the object took somewhere on the order of
micro- to milli-seconds, while destroying it and creating a new
object would take something like several seconds to a minute or so.

There are also times that you have something like:

X objects[whatever];

if (something) {
initialize objects
}
use objects;

If we attempt to move the definition of objects to the 'initialize'
section, it'll go out of scope before we can use it.
[ code elided ]

Something like that could probably help some things -- but certainly
not others. I don't see it accomplishing anything in the situation
outlined above, for one example.

I'm not sure how this would be an improvement in any case. It looks
more complex and less versatile than what I was thinking of, which
would be more on the order of a templated version of BSD's bzero.
--
Later,
Jerry.

The universe is a figment of its own imagination.
Loading...