471,058 Members | 1,004 Online

# loop vs memset to initialize array.. different results?

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

Jul 27 '06 #1
22 26315
silversurfer2025 wrote:
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?
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
--
Jul 27 '06 #2

"silversurfer2025" <ki****@web.dewrote in message
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,
Have you proven with timing or profiling that there
is indeed an efficiency problem?
I changed it to use
memset

Don't.
and I get totally different results.. How can this be?
Because the representation of 0.0 isn't necessarily
all-bits-zero.
>
Here is the example:

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'.

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) */
}
}

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

Jul 27 '06 #3

Mike Wahler schrieb:
"silversurfer2025" <ki****@web.dewrote in message
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,

Have you proven with timing or profiling that there
is indeed an efficiency problem?
I changed it to use
memset

Don't.
OK ;)
>
and I get totally different results.. How can this be?

Because the representation of 0.0 isn't necessarily
all-bits-zero.

Here is the example:

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..
>
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};
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?
/* (all elements now have value of zero) */
}
}

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..
>
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
>
std::vector<float>(filtersize, std::vector<float>(filtersize));

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

-Mike
Tim

Jul 27 '06 #4
silversurfer2025 wrote:
>[..]
But if you want all values to be zero, you could simply
initialize the array when you create it:

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?
Variable-sized object? Are you using g++ extensions? You might want
to consider a dynamic array then...
[..]
V
--
Jul 27 '06 #5

"silversurfer2025" <ki****@web.dewrote in message
>
Mike Wahler schrieb:
>"silversurfer2025" <ki****@web.dewrote in message
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,

Have you proven with timing or profiling that there
is indeed an efficiency problem?
I changed it to use
memset

Don't.
OK ;)
>>
and I get totally different results.. How can this be?

Because the representation of 0.0 isn't necessarily
all-bits-zero.
>
Here is the example:

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?
>
>>
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};
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?
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.
>
>/* (all elements now have value of zero) */
}
}

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
Jul 27 '06 #6

Victor Bazarov schrieb:
silversurfer2025 wrote:
[..]
But if you want all values to be zero, you could simply
initialize the array when you create it:

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?

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
>
[..]

V
--
Jul 27 '06 #7
Mike Wahler wrote:
>Here is the example:

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
Jul 27 '06 #8
Andrey Tarasevich wrote:
>
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
Jul 27 '06 #9

"silversurfer2025" <ki****@web.dewrote in message
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?
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

Jul 27 '06 #10

Howard schrieb:
"silversurfer2025" <ki****@web.dewrote in message
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?

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
>
-Howard
Jul 28 '06 #11
ki****@web.de says...

[ ... initializing an array of float to 0 ]
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.
Jul 28 '06 #12
Jerry Coffin posted:
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
Jul 28 '06 #13
In article <q6*******************@news.indigo.ie>, fg*******@SPAM.com
says...
Jerry Coffin posted:
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.
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.
Jul 28 '06 #14
Jerry Coffin posted:
>Set the first five characters of a string to asterisks:

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...)

I was referring to homemade, null-terminated, char buffer strings:

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

memset(str,'*',5);

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.

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
Jul 28 '06 #15
In article <rS*******************@news.indigo.ie>, fg*******@SPAM.com
says...

[ ... ]
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.

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.
Jul 28 '06 #16
In article <MP************************@news.sunsite.dk>,
jc*****@taeus.com says...

[ ... ]
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.
Jul 28 '06 #17
Jerry Coffin posted:
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
Jul 29 '06 #18
In article <7L*******************@news.indigo.ie>, fg*******@SPAM.com
says...
Jerry Coffin posted:
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.
Jul 29 '06 #19
Jerry Coffin posted:
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
Jul 29 '06 #20
In article <Wd*******************@news.indigo.ie>, fg*******@SPAM.com
says...
Jerry Coffin posted:
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.
Jul 29 '06 #21
Jerry Coffin posted:
In article <Wd*******************@news.indigo.ie>, fg*******@SPAM.com
says...
>Jerry Coffin posted:
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
Jul 29 '06 #22
In article <th*******************@news.indigo.ie>, fg*******@SPAM.com
says...

[ ... ]
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.
If anything, we could have a template function as follows:
[ 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.
Jul 29 '06 #23

### This discussion thread is closed

Replies have been disabled for this discussion.