470,602 Members | 1,728 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 470,602 developers. It's quick & easy.

is it safe to zero float array with memset?

Hello,
I have to initialize all elements of a very big float point array to
zero. It seems memset(a, 0, len) is faster than a simple loop. I just
want to know whether it is safe to do so, since I know it's danger to
initialize NULL pointers this way. But how about floats?

Zhang Le

Nov 15 '05 #1
26 24345
69dbb24b2db3daad932c457ccc...@gmail.com wrote:
Hello,
I have to initialize all elements of a very big float point array to
zero. It seems memset(a, 0, len) is faster than a simple loop. I just
want to know whether it is safe to do so, since I know it's danger to
initialize NULL pointers this way. But how about floats?


Is the memory for the array dynamically allocated? If not, you could
do this:
float a[len] = {0};

Using memset to set a value to zero is only safe on integer types, not
floating point types or pointers.

Robert Gamble

Nov 15 '05 #2
On 2005-07-22 09:59:28 -0500, 69***************************@gmail.com said:
Hello,
I have to initialize all elements of a very big float point array to
zero. It seems memset(a, 0, len) is faster than a simple loop. I just
want to know whether it is safe to do so, since I know it's danger to
initialize NULL pointers this way. But how about floats?

Zhang Le


It depends. If it's an array of float yes, of it's an array of float*
you're setting all ptrs to NULL, safe anyway.
--
Sensei <se******@tin.it>

cd /pub
more beer

Nov 15 '05 #3
Sensei wrote:
On 2005-07-22 09:59:28 -0500, 69***************************@gmail.com said:
Hello,
I have to initialize all elements of a very big float point array to
zero. It seems memset(a, 0, len) is faster than a simple loop. I just
want to know whether it is safe to do so, since I know it's danger to
initialize NULL pointers this way. But how about floats?

Zhang Le


It depends. If it's an array of float yes, of it's an array of float*
you're setting all ptrs to NULL, safe anyway.


You are making little sense. You said it depends, then you go on to
say that it is safe in either case? Well, you are wrong on all counts.
In either case there is no guarantee made by the C Standard that
either of these scenerios is safe. NULL need not be all-bits zero,
neither does float need to use this as a representation for zero (or
anything else for that matter).

Robert Gamble

Nov 15 '05 #4
Thanks for the reply, I now think it's unsafe to use memset.

Interestingly, from FAQ 5.17:
http://www.eskimo.com/~scs/C-faq/s5.html

I find there are some cases where NULL is not zero, which means the
only portable way to test a pointer aginst NULL is via:
if (p != NULL) {...}
if (p == NULL) {...}

And if (p), if (!p) will fail on these systems if I understand
correctly. Horrible things will happy consider how many of us write
code this way,.

Zhang Le

Nov 15 '05 #5
69***************************@gmail.com wrote:
Hello,
I have to initialize all elements of a very big float point array to
zero. It seems memset(a, 0, len) is faster than a simple loop. I just
want to know whether it is safe to do so, since I know it's danger to
initialize NULL pointers this way. But how about floats?

Zhang Le


Search comp.lang.c for "float all bits 0" and you'll find nice large
discussions on this.

It may be that you can still be portable and use memset, for example
you could have a function that is like below (not checked)

void clear_array(double *array, size_t size)
{
/* following define is C99, but you may find others on
other implementations. Or define other conditions under
which you want to use memset */
#if defined(__STDC_IEC_559__)
memset(array, 0, size * sizeof(double)
#else
size_t i;

for (i = 0; i < size; i++) {
array[i] = 0.0;
}
#endif
}

It would only do the memset if IEEE754 math is used. In that
case, as I understand it, all bits 0 is 0. You might be able
to get other indicators that memset is to be used as well.

-David

Nov 15 '05 #6
Sorry for my last post. Again from FAQ 5.3 I found both if (p) and if
(!p) are correct regardless of the value of NULL.

Zhang Le

Nov 15 '05 #7
69***************************@gmail.com wrote:
Hello,
I have to initialize all elements of a very big float point array to
zero. It seems memset(a, 0, len) is faster than a simple loop. I just
want to know whether it is safe to do so, since I know it's danger to
initialize NULL pointers this way. But how about floats?


No, it's not safe. All bits zero may not represent a floating point 0.0
and could be a trap representation.
--
Flash Gordon
Living in interesting times.
Although my email address says spam, it is real and I read it.
Nov 15 '05 #8
69***************************@gmail.com wrote:

Thanks for the reply, I now think it's unsafe to use memset.

Interestingly, from FAQ 5.17:
http://www.eskimo.com/~scs/C-faq/s5.html

I find there are some cases where NULL is not zero, which means the
only portable way to test a pointer aginst NULL is via:
if (p != NULL) {...}
if (p == NULL) {...}

And if (p), if (!p) will fail on these systems if I understand
correctly. Horrible things will happy consider how many of us write
code this way,.


My understanding (and I'm sure someone who knows the standard better
than, I will correct me if I'm wrong) is that NULL compares to zero
even on platforms where NULL is not all-bits-zero.

Therefore, "if (p)" is the same as "if (p != NULL)" even on not-all-
bits-zero platforms.

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:Th*************@gmail.com>
Nov 15 '05 #9
On 2005-07-22 10:32:55 -0500, "Robert Gamble" <rg*******@gmail.com> said:
It depends. If it's an array of float yes, of it's an array of float*
you're setting all ptrs to NULL, safe anyway.
You are making little sense. You said it depends, then you go on to
say that it is safe in either case? Well, you are wrong on all counts.


I always memset-ed before any use! :)

In either case there is no guarantee made by the C Standard that
either of these scenerios is safe. NULL need not be all-bits zero,
neither does float need to use this as a representation for zero (or
anything else for that matter).


Safety in my opinion is not memory I don't have rights to access.
Making a zero-bit float or ptr must be safe as long as the memory is
accessible. Isn't it? For this matter, setting all bytes to any value
(even random) is safe. Not meaningful, but safe.

--
Sensei <se******@tin.it>

cd /pub
more beer

Nov 15 '05 #10
On Fri, 22 Jul 2005 15:13:49 -0500, Sensei wrote:

....
In either case there is no guarantee made by the C Standard that
either of these scenerios is safe. NULL need not be all-bits zero,
neither does float need to use this as a representation for zero (or
anything else for that matter).


Safety in my opinion is not memory I don't have rights to access.
Making a zero-bit float or ptr must be safe as long as the memory is
accessible. Isn't it? For this matter, setting all bytes to any value
(even random) is safe. Not meaningful, but safe.


Setting the bits can be done safely. Reading the value as a float or
pointer variable later is not, that can have undefined behaviour if you
happened to set a trap representation which can be as unsafe as bad memory
accesses.

Lawrence

Nov 15 '05 #11
69***************************@gmail.com writes:
I have to initialize all elements of a very big float point array to
zero. It seems memset(a, 0, len) is faster than a simple loop. I just
want to know whether it is safe to do so, since I know it's danger to
initialize NULL pointers this way. But how about floats?


It's possible, but rare, for all-bits-zero not to be the
representation of a floating-point 0.0.

Here's an approach that might be useful if you're concerned about both
maximal portability and good performance:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

static int float_zero_is_all_bits_zero(void)
{
float f = 0.0;
unsigned char zero_bytes[sizeof f] = { 0 };
return memcmp(&f, zero_bytes, sizeof f) == 0;
}

void set_float_zero(float *dest, size_t count)
{
static int initialized = 0;
int may_use_memset;

if (!initialized) {
may_use_memset = float_zero_is_all_bits_zero();
initialized = 1;
}

if (may_use_memset) {
memset(dest, 0, count * sizeof *dest);
}
else {
size_t i;
for (i = 0; i < count; i ++) {
dest[i] = 0.0;
}
}
}

#define ARR_LEN 1000

int main(void)
{
float *arr = malloc(ARR_LEN * sizeof *arr);
set_float_zero(arr, ARR_LEN);
return 0;
}

The first call to set_float_zero() will invoke
float_zero_is_all_bits_zero() to determine how 0.0 is actually
represented; it then uses memset() if it's safe, and falls back to an
explicit loop if it isn't. On calls after the first, it merely checks
a single flag.

This is useful if the memset() is significantly faster than the
explicit loop, something that is not at all obvious. If you're
concerned about performance, you should measure the actual performance
of both techniques. A sufficiently clever compiler might even
transform the loop to the equivalent of a memset() call -- or even
something faster, since it knows that the array is aligned.

Interestingly, the compiler I tried (gcc 3.4.4) warned that
"`may_use_memset' might be used uninitialized in this function". In
fact, the use of the "initialized" variable guarantees that this won't
happen, but the compiler wasn't able to figure this out. You can
always inhibit the warning by initializing may_use_memset.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #12
>>> It depends. If it's an array of float yes, of it's an array of float*
you're setting all ptrs to NULL, safe anyway.
You are making little sense. You said it depends, then you go on to
say that it is safe in either case? Well, you are wrong on all counts.


I always memset-ed before any use! :)

In either case there is no guarantee made by the C Standard that
either of these scenerios is safe. NULL need not be all-bits zero,
neither does float need to use this as a representation for zero (or
anything else for that matter).


Safety in my opinion is not memory I don't have rights to access.
Making a zero-bit float or ptr must be safe as long as the memory is
accessible. Isn't it?


Not necessarily if you use the results afterward *as floats* or *as
pointers to float*.
For this matter, setting all bytes to any value
(even random) is safe. Not meaningful, but safe.


Not if you then try to use the value as a float or as a pointer.
Whatever bit pattern you set a float to might be a trapping NaN.
A pointer might compare unequal to NULL and then smegfault when you
try to dereference it, or it might even cause an exception when you
load it into an address register (no dereference needed).

Gordon L. Burditt
Nov 15 '05 #13
In article <ln************@nuthaus.mib.org>,
Keith Thompson <ks***@mib.org> wrote:
void set_float_zero(float *dest, size_t count)
{
static int initialized = 0;
int may_use_memset;

if (!initialized) {
may_use_memset = float_zero_is_all_bits_zero();
initialized = 1;
}
[snip]
Interestingly, the compiler I tried (gcc 3.4.4) warned that
"`may_use_memset' might be used uninitialized in this function". In
fact, the use of the "initialized" variable guarantees that this won't
happen, but the compiler wasn't able to figure this out. You can
always inhibit the warning by initializing may_use_memset.


Does the warning go away if you make may_use_memset static?
dave

--
Dave Vandervies dj******@csclub.uwaterloo.ca
[A]n "outrage" is when someone beats up innocent bystanders in the streets,
not when your favourite programming language has a feature you dislike.
--Richard Bos in comp.lang.c
Nov 15 '05 #14
Kenneth Brody wrote:
My understanding (and I'm sure someone who knows the standard better
than, I will correct me if I'm wrong) is that NULL compares to zero
even on platforms where NULL is not all-bits-zero.

Therefore, "if (p)" is the same as "if (p != NULL)" even on not-all-
bits-zero platforms.


Just to help you sleep well tonight, I can assure you that you are 100%
correct, which makes a change around here. (I've just been reading today's
feed, and what a sorry collection of articles it is.)
--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
mail: rjh at above domain
Nov 15 '05 #15
<69***************************@gmail.com> wrote

I have to initialize all elements of a very big float point array to
zero. It seems memset(a, 0, len) is faster than a simple loop. I just
want to know whether it is safe to do so, since I know it's danger to
initialize NULL pointers this way. But how about floats?

No, but it's "safe enough". If you do need the speed increment, it is
probably worth the small risk that someone will run your code on a system
that doesn't use all bits zero for float 0.0.
Nov 15 '05 #16
"Malcolm" <re*******@btinternet.com> writes:
<69***************************@gmail.com> wrote

I have to initialize all elements of a very big float point array to
zero. It seems memset(a, 0, len) is faster than a simple loop. I just
want to know whether it is safe to do so, since I know it's danger to
initialize NULL pointers this way. But how about floats?

No, but it's "safe enough". If you do need the speed increment, it is
probably worth the small risk that someone will run your code on a system
that doesn't use all bits zero for float 0.0.


I don't *quite* agree that it's "safe enough".

If I were going to use memset() to zero an array of floats, the first
thing I'd do is measure the performance to see if memset() really is
faster. If it isn't, there's no point in using anything other than an
explicit loop, which is known to be safe.

If I found that memset() really is faster, *and* that the increase in
performance is actually significant, I'd probably write a test
function, to be invoked once at program startup, that checks whether
0.0 really is all-bits-zero. If it isn't, it would abort the program.
If the program is eventually ported to a system were 0.0 *isn't*
all-bits-zero, it will then abort immediately rather than running
and giving mysteriously incorrect results.

If even invoking the test function once is a problem, I'd move the
test into the build procedure, so the program won't even build unless
it's first proven that 0.0 is all-bits-zero.

For that matter, as long as I'm messing with the build procedure, I
might as well have it set a macro that indicates whether memset() is
safe, and use that in the code to determine at compilation time which
method to use.

The only problem with this is that it's difficult to find a platform
on which 0.0 *isn't* all-bits-zero, so any code that assumes it isn't
may not be tested properly.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #17
On 2005-07-22 15:31:24 -0500, go****@hammy.burditt.org (Gordon Burditt) said:
Not necessarily if you use the results afterward *as floats* or *as
pointers to float*.

Not if you then try to use the value as a float or as a pointer.
Whatever bit pattern you set a float to might be a trapping NaN.
A pointer might compare unequal to NULL and then smegfault when you
try to dereference it, or it might even cause an exception when you
load it into an address register (no dereference needed).

Well, yes and no. I mean, when I was using DOS (more than a decade
ago), an important pointer was the one at the interrupt vector table,
or the video memory (0x0000 and 0xA000 if I remember), and it was
always done by setting a ptr to a number. Resetting the IVT by
memsetting, was dangerous, but if you wanted to do some tricks, it was
a possible choice.

The meaning of what it contains, should be of no concern for C, as it's
a matter of the implementation itself.

Whether you're accessing a non-readable memory by deferencing a weird
ptr, it's again the implementation, but setting the ptr still results
in a safe operation. Writing and even reading to that location is,
naturally, not safe.

For floats, again, NaN may be a result of a misinterpretation of what
the float was meant to be, but it cannot be considered unsafe from C
point of view.

It's the programmer who must be sure of all the meanings :)

--
Sensei <se******@tin.it>

cd /pub
more beer

Nov 15 '05 #18
On 2005-07-22 16:22:51 -0500, Lawrence Kirby <lk****@netactive.co.uk> said:

Setting the bits can be done safely. Reading the value as a float or
pointer variable later is not, that can have undefined behaviour if you
happened to set a trap representation which can be as unsafe as bad memory
accesses.

Lawrence


Yes, it really depends on what those pointers and floats mean.
--
Sensei <se******@tin.it>

cd /pub
more beer

Nov 15 '05 #19
69***************************@gmail.com wrote:
Hello,
I have to initialize all elements of a very big float point array to
zero. It seems memset(a, 0, len) is faster than a simple loop. I just
want to know whether it is safe to do so, since I know it's danger to
initialize NULL pointers this way. But how about floats?


Yes, it is safe. Not one hundred percent safe, but safer
than riding in an automobile, say, or eating home-cooked food.

Here's the bigger question: Why do you care? Frankly, if
your program spends a significant amount of its running time
setting things to zero (as opposed to filling them with Useful
Information), there is probably something wrong with the design
of your program. In four decades of programming, I have run
into only ONE situation where the speed of zeroing memory was
important -- and I will bet dollars to doughnuts that your
program is not (or should not be) Case Number Two.

--
Eric Sosman
es*****@acm-dot-org.invalid
Nov 15 '05 #20
>> Not necessarily if you use the results afterward *as floats* or *as
pointers to float*.

Not if you then try to use the value as a float or as a pointer.
Whatever bit pattern you set a float to might be a trapping NaN.
A pointer might compare unequal to NULL and then smegfault when you
try to dereference it, or it might even cause an exception when you
load it into an address register (no dereference needed).
Well, yes and no. I mean, when I was using DOS (more than a decade
ago), an important pointer was the one at the interrupt vector table,
or the video memory (0x0000 and 0xA000 if I remember), and it was
always done by setting a ptr to a number. Resetting the IVT by
memsetting, was dangerous, but if you wanted to do some tricks, it was
a possible choice.


But since C does not guarantee that this same code will work on a
PDP-11, it's not safe. "undefined behavior" doesn't guarantee that
it won't do exactly what you expect it to do (until, of course, the
boss is watching).
The meaning of what it contains, should be of no concern for C, as it's
a matter of the implementation itself.
If it's a matter of the implementation itself, *IT'S NOT SAFE*.
Whether you're accessing a non-readable memory by deferencing a weird
ptr, it's again the implementation, but setting the ptr still results
in a safe operation. Writing and even reading to that location is,
naturally, not safe.
Setting the pointer *AND THEN USING (but not DEREFERENCING) IT*
isn't safe. The following can possibly abort the program:

char *p = 0xdeadbeef; /* or some other oddball hex constant */

p; /* note that I didn't say *p here */

Note, for example, that in protected mode putting certain bit
patterns into a segment register on an i386 platform cause traps
without even trying to dereference anything.

For floats, again, NaN may be a result of a misinterpretation of what
the float was meant to be, but it cannot be considered unsafe from C
point of view.
Anything that is not guaranteed to be safe from the C point of view
is unsafe from the C point of view.
It's the programmer who must be sure of all the meanings :)


Gordon L. Burditt
Nov 15 '05 #21
On 2005-07-22 21:40:17 -0500, go***********@burditt.org (Gordon Burditt) said:
But since C does not guarantee that this same code will work on a
PDP-11, it's not safe. "undefined behavior" doesn't guarantee that
it won't do exactly what you expect it to do (until, of course, the
boss is watching).
I see.

Setting the pointer *AND THEN USING (but not DEREFERENCING) IT*
isn't safe. The following can possibly abort the program:

char *p = 0xdeadbeef; /* or some other oddball hex constant */

p; /* note that I didn't say *p here */
Yes, and even reading from p can cause an abort.

Note, for example, that in protected mode putting certain bit
patterns into a segment register on an i386 platform cause traps
without even trying to dereference anything.


Yes, what I'm saying is that, as long as you don't mess with memory
addresses (*), and as long as you don't give a meaning to the floats,
it's safe, not meaningful, completely random, but safe. While using
those values just because you trust your god, then Murphy's laws will
give you a good lessons :)

(*) I said in fact, ``you don't read from it (or write)'', i.e. any use
of it is dangerous, since it involves reading and/or writing...

--
Sensei <se******@tin.it>

cd /pub
more beer

Nov 15 '05 #22

"Keith Thompson" <ks***@mib.org> wrote

If I found that memset() really is faster, *and* that the increase in
performance is actually significant,
I was going to make that point. However the OP said it was faster, so I
decided to take it as a given. In fact, as Eric Sosman pointed out,
situations in which zeroing memory is the bottleneck are fairly rare.
I'd probably write a test
function, to be invoked once at program startup, that checks whether
0.0 really is all-bits-zero. If it isn't, it would abort the program.

That's quite a good I idea. The problem with the way I work is that I tend
to have lots of functions and files which I shift between programs. So the
"superfast matrix multiply", which does need a lightning fast zeroing
operation, might be called from three or four separate main()s.

Nov 15 '05 #23

"Richard Heathfield" <in*****@address.co.uk.invalid> wrote
Just to help you sleep well tonight, I can assure you that you are 100%
correct, which makes a change around here. (I've just been reading today's
feed, and what a sorry collection of articles it is.)

I've noticed that a lot of the talented regs seem to have disappeared.

I'm thinking of starting a series on "how to use C effectively" that goes
beyond details of the standard to look more at the software engineering side
of C programming.

Do you think that would attract people back?
Nov 15 '05 #24


Keith Thompson wrote:

[snip]

void set_float_zero(float *dest, size_t count)
{
static int initialized = 0;
int may_use_memset;

if (!initialized) {
may_use_memset = float_zero_is_all_bits_zero();
initialized = 1;
}

if (may_use_memset) {
memset(dest, 0, count * sizeof *dest);
}
else {
size_t i;
for (i = 0; i < count; i ++) {
dest[i] = 0.0;
}
}
}

[snip]
Interestingly, the compiler I tried (gcc 3.4.4) warned that
"`may_use_memset' might be used uninitialized in this function". In
fact, the use of the "initialized" variable guarantees that this won't
happen, but the compiler wasn't able to figure this out. You can


No, you are actually accessing uninitialized may_use_memset on second
call
of 'set_float_zero' function. may_use_memset should be a static
variable.

Krishanu

Nov 15 '05 #25
"Krishanu Debnath" <kr**************@gmail.com> writes:
Keith Thompson wrote:

[snip]

void set_float_zero(float *dest, size_t count)
{
static int initialized = 0;
int may_use_memset;

if (!initialized) {
may_use_memset = float_zero_is_all_bits_zero();
initialized = 1;
}

if (may_use_memset) {
memset(dest, 0, count * sizeof *dest);
}
else {
size_t i;
for (i = 0; i < count; i ++) {
dest[i] = 0.0;
}
}
}


[snip]
Interestingly, the compiler I tried (gcc 3.4.4) warned that
"`may_use_memset' might be used uninitialized in this function". In
fact, the use of the "initialized" variable guarantees that this won't
happen, but the compiler wasn't able to figure this out. You can


No, you are actually accessing uninitialized may_use_memset on second
call
of 'set_float_zero' function. may_use_memset should be a static
variable.


Good catch, thanks.

In case anybody wants to use this code, here it is again with the
error corrected.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

static int float_zero_is_all_bits_zero(void)
{
float f = 0.0;
unsigned char zero_bytes[sizeof f] = { 0 };
return memcmp(&f, zero_bytes, sizeof f) == 0;
}

void set_float_zero(float *dest, size_t count)
{
static int initialized = 0;
static int may_use_memset;

if (!initialized) {
may_use_memset = float_zero_is_all_bits_zero();
initialized = 1;
}

if (may_use_memset) {
memset(dest, 0, count * sizeof *dest);
}
else {
size_t i;
for (i = 0; i < count; i ++) {
dest[i] = 0.0;
}
}
}

#define ARR_LEN 1000

int main(void)
{
float *arr = malloc(ARR_LEN * sizeof *arr);
set_float_zero(arr, ARR_LEN);
return 0;
}

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #26
On Fri, 22 Jul 2005 21:46:10 GMT, Keith Thompson
<ks***@mib.org> wrote:
For that matter, as long as I'm messing with the build procedure, I
might as well have it set a macro that indicates whether memset() is
safe, and use that in the code to determine at compilation time which
method to use.

The only problem with this is that it's difficult to find a platform
on which 0.0 *isn't* all-bits-zero, so any code that assumes it isn't
may not be tested properly.


The other big problem is that such a platform may well be used with
cross-compilation, and runnng the test program on the target may well
not be possible at build time.

If the test can be done at runtime, I would tend to have it set a flag
so that the "clear an array of floats" function could determine which
algorithm is fastest and do it that way. That's what a number of
libraries have done, for instance with systems which may or may not have
floating point processors (another method, especially if there are
several functions depending on the same thing, is to use a jump or
function pointer table and select the right one at startup).

Chris C
Nov 15 '05 #27

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

14 posts views Thread by dam_fool_2003 | last post: by
33 posts views Thread by Zytan | last post: by
2 posts views Thread by Peter | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.