loop vs memset to initialize array.. different results?

S

silversurfer2025

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[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
 
V

Victor Bazarov

silversurfer2025 said:
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[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
 
M

Mike Wahler

silversurfer2025 said:
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[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
 
S

silversurfer2025

Mike said:
silversurfer2025 said:
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[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) */


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
vector. (please do not ask!)
std::vector<float>(filtersize, std::vector<float>(filtersize));

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

-Mike

Tim
 
V

Victor Bazarov

silversurfer2025 said:
[..]
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
 
M

Mike Wahler

silversurfer2025 said:
Mike said:
silversurfer2025 said:
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[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.
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
 
S

silversurfer2025

Victor said:
silversurfer2025 said:
[..]
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
 
A

Andrey Tarasevich

Mike said:
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).
 
P

Pete Becker

Andrey said:
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.
 
H

Howard

silversurfer2025 said:
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[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
 
S

silversurfer2025

Howard said:
silversurfer2025 said:
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[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
 
J

Jerry Coffin

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

Frederick Gotham

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

Jerry Coffin

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

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

Frederick Gotham

Jerry Coffin posted:
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.
 
J

Jerry Coffin

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

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."
 
F

Frederick Gotham

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

Jerry Coffin

Jerry Coffin posted:


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

Frederick Gotham

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] = {};
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top