loop vs memset to initialize array.. different results?

Discussion in 'C++' started by silversurfer2025, Jul 27, 2006.

  1. 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
     
    silversurfer2025, Jul 27, 2006
    #1
    1. Advertising

  2. 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[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
     
    Victor Bazarov, Jul 27, 2006
    #2
    1. Advertising

  3. silversurfer2025

    Mike Wahler Guest

    "silversurfer2025" <> wrote in message
    news:...
    > 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
     
    Mike Wahler, Jul 27, 2006
    #3
  4. Mike Wahler schrieb:

    > "silversurfer2025" <> wrote in message
    > news:...
    > > 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) */
    >
    > > }
    > > }
    > >
    > > 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
    vector. (please do not ask!)

    >
    > std::vector<float>(filtersize, std::vector<float>(filtersize));
    >
    > /* All elements now have values of zero. */
    >
    > -Mike


    Tim
     
    silversurfer2025, Jul 27, 2006
    #4
  5. 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
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Jul 27, 2006
    #5
  6. silversurfer2025

    Mike Wahler Guest

    "silversurfer2025" <> wrote in message
    news:...
    >
    > Mike Wahler schrieb:
    >
    >> "silversurfer2025" <> wrote in message
    >> news:...
    >> > 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.

    >
    >> /* (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
     
    Mike Wahler, Jul 27, 2006
    #6
  7. 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
    > --
    > Please remove capital 'A's when replying by e-mail
    > I do not respond to top-posted replies, please don't ask
     
    silversurfer2025, Jul 27, 2006
    #7
  8. 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
     
    Andrey Tarasevich, Jul 27, 2006
    #8
  9. silversurfer2025

    Pete Becker Guest

    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
    most of the answers.
     
    Pete Becker, Jul 27, 2006
    #9
  10. silversurfer2025

    Howard Guest

    "silversurfer2025" <> wrote in message
    news:...
    > 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
     
    Howard, Jul 27, 2006
    #10
  11. Howard schrieb:

    > "silversurfer2025" <> wrote in message
    > news:...
    > > 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

    >
    > -Howard
     
    silversurfer2025, Jul 28, 2006
    #11
  12. silversurfer2025

    Jerry Coffin Guest

    In article <>,
    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.
     
    Jerry Coffin, Jul 28, 2006
    #12
  13. 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
     
    Frederick Gotham, Jul 28, 2006
    #13
  14. silversurfer2025

    Jerry Coffin Guest

    In article <q6ryg.11962$>,
    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.
     
    Jerry Coffin, Jul 28, 2006
    #14
  15. 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
     
    Frederick Gotham, Jul 28, 2006
    #15
  16. silversurfer2025

    Jerry Coffin Guest

    In article <rStyg.11969$>,
    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.
     
    Jerry Coffin, Jul 28, 2006
    #16
  17. silversurfer2025

    Jerry Coffin Guest

    In article <>,
    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.
     
    Jerry Coffin, Jul 28, 2006
    #17
  18. 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
     
    Frederick Gotham, Jul 29, 2006
    #18
  19. silversurfer2025

    Jerry Coffin Guest

    In article <7LAyg.11977$>,
    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.
     
    Jerry Coffin, Jul 29, 2006
    #19
  20. 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
     
    Frederick Gotham, Jul 29, 2006
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Joakim Hove

    memset to initialize double array?

    Joakim Hove, Nov 8, 2005, in forum: C Programming
    Replies:
    3
    Views:
    885
    SM Ryan
    Nov 8, 2005
  2. Replies:
    24
    Views:
    10,779
    arizonace
    Mar 12, 2013
  3. Replies:
    5
    Views:
    4,372
    CBFalconer
    Dec 29, 2008
  4. a s
    Replies:
    16
    Views:
    4,761
    JustJohn
    Mar 8, 2011
  5. Isaac Won
    Replies:
    9
    Views:
    447
    Ulrich Eckhardt
    Mar 4, 2013
Loading...

Share This Page