473,890 Members | 1,394 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

removing a loop cause it to go at half the speed?

Hi

I was doing a simple test of the speed of a "maths" operation and when I
tested it I found that removing the loop that initialises the data array
for the operation caused the whole program to spend twice the time to
complete. If the loop is included it takes about 7.48 seconds to
complete, but when removed it takes about 11.48 seconds.

Does anybody have a suggestion as to why this is so and whether I can
trust the results of the code as it is below?

/tom
The code was compiled on linux 2.6.3 with gcc 3.3.2 and glibc 2.2.3
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>

int main(int argc, char *argv[])
{
int total = 0;
int count = 65500;
signed int data[count];

/* Initialising array loop */
for(int c=0; c<count; c++) {
data[c]=1+(int) (2000000000.0*r and()/(RAND_MAX+1.0)) ;
}

struct timeval start_time;
struct timeval end_time;

gettimeofday(&s tart_time, NULL);

for(int d=0; d<50000; d++) {
for(int c=0; c<count; c++) {
total += data[c];
}
}
gettimeofday(&e nd_time, NULL);

double t1=(start_time. tv_sec*1000)+(s tart_time.tv_us ec/1000.0);
double t2=(end_time.tv _sec*1000)+(end _time.tv_usec/1000.0);

printf("Elapsed time (ms): %.6lf\n", t2-t1);
printf("Total: %u\n", total);

return(0);
}
Mar 15 '06
102 4596
tom fredriksen wrote:

(long quotes)
Chris Dollin wrote:
tom fredriksen wrote:
Richard Heathfield wrote:
tom fredriksen said:

> Wrong, it does not cause undefined behaviour because the values used
> does not require a specific set of values or a value range.
Wrong.

C89 draft:

* Undefined behavior --- behavior, upon use of a nonportable or
erroneous program construct, of erroneous data, or of
indeterminately-valued objects, for which the Standard imposes no
requirements.

C99 final:

"Certain object representations need not represent a value of the
object type. If the stored value of an object has such a representation
and is read by an lvalue expression that does not have character type,
the behavior is undefined."
That does not contradict what I am saying. These statements only define
what undefined behaviour is, in context of the standard and the
language, nothing more. It does not say using such a value must demand
undefined behaviour.


It says using such a value /produces/ undefined behaviour: if you do
it, you can no longer appeal to the C standard for the remaining
behaviour of your code. An implementation can do /anything it likes/.

Now, you may happen to know - or believe - that your implementation
will do something harmless. And you may be right. But this is not
because of the semantics of C, but because of some
implementation-specific behaviour, which in turn may be accidental.

When we say that such-and-such is undefined behaviour, we mean that
the behaviour of the program can no longer be predicted from the
semantics of C,


Can you then explain to me how it is that you think the behaviour of my
code can not be predicted?


Certainly.

When you don't initialise the data array, the line:

total += data[c]

references an indeterminately-valued object. This produces undefined
behaviour. Therefore, the further behaviour of your code cannot be
predicted /from the C standard/: you must use additional information.

--
Chris "sparqling" Dollin
"Who do you serve, and who do you trust?"
Mar 16 '06 #31
Chris Dollin wrote:
Can you then explain to me how it is that you think the behaviour of my
code can not be predicted?
Certainly.

When you don't initialise the data array, the line:

total += data[c]

references an indeterminately-valued object.


Correct.
This produces undefined behaviour.
Therefore, the further behaviour of your code cannot be
predicted /from the C standard/: you must use additional information.


You see, even though the standard defines it as undefined behaviour,
does not practically make it undefined behaviour. It is only defined as
such because the writers of the standard are not in a position to guess
such a variables value or use for all possible future programs.

I think there is no point continuing the discussion. Because if you only
look at it literally, as you do, then you are correct, I dont dispute
that. But if you consider the pragmatics of it, in addition to the
literal meaning, which you should when you are programming, then you are
wrong.

/tom

Mar 16 '06 #32
tom fredriksen wrote:
Chris Dollin wrote:
Can you then explain to me how it is that you think the behaviour of my
code can not be predicted?
Certainly.

When you don't initialise the data array, the line:

total += data[c]

references an indeterminately-valued object.


Correct.
This produces undefined behaviour.
> Therefore, the further behaviour of your code cannot be
> predicted /from the C standard/: you must use additional information.


You see, even though the standard defines it as undefined behaviour,
does not practically make it undefined behaviour.


In what way have I not been explicit about this?

"the further behaviour of your code cannot be predicted /from the C
standard/: you must use additional information."

"Undefined behaviour" in this newsgroup /means/ "behaviour left undefined
by the [relevant] C standard". So, for portability, /avoid/ UB, because
even if you know (or think you know) what will happen on the machine you
happen to be running on today, you don't know what will happen tomorrow,
or on a different machine elsewhere.
It is only defined as such because the writers of the standard are
not in a position to guess such a variables value or use for all
possible future programs.
It's defined as such because different implementations have been known to
do different things with this, or similar, situations, it's very hard
to define the exact line to cross, and even if you /could/ it probably
wouldn't help.

Here's a well-known type of undefined bahviour:

int eg() { int i = 17; return i++ + ++i; }

An interesting variety of "answers" are available, all correct.
I think there is no point continuing the discussion. Because if you only
look at it literally, as you do, then you are correct, I dont dispute
that. But if you consider the pragmatics of it, in addition to the
literal meaning, which you should when you are programming, then you are
wrong.


The pragmatics are

* avoid code with undefined behaviour
* if you can't, justify it with additional standards
* if you can't, have sanity checks and document it

--
Chris "sparqling" Dollin
"Who do you serve, and who do you trust?"
Mar 16 '06 #33
Chris Dollin wrote:
tom fredriksen wrote:

total += data[c]


Explain to me how this statement causes undefined behaviour and how its
behaviour will be different on different architectures.
The difference here is whether data[c] has a value set by me instead of
a random value from some historic use of that memory address.

The only thing happening here is an addition of two binary values from a
memory address to another memory address or register, as defined in
the language specification for the "+=" operator.

I can imagine a system where the compiler or the architecture causes a
program using an uninitialised variable to abort or cast an exception /
interrupt etc. if thats what you mean then agreed, than can happen, but
I don't think its a good idea.

/tom
Mar 16 '06 #34

tom fredriksen wrote:
Chris Dollin wrote:
tom fredriksen wrote:
>>> total += data[c]


Explain to me how this statement causes undefined behaviour and how its
behaviour will be different on different architectures.
The difference here is whether data[c] has a value set by me instead of
a random value from some historic use of that memory address.


Why are you so sure the same memory area would have been used before,
and even if it was, that it's not going to contain something that's a
trap representation for the type that `data` above is? That, exactly,
is why it's *undefined* behaviour. As far as C Standard is concerned,
the memory may have just been shipped from Vladivostok, after being
used on a Russian nuclear submarine.
The only thing happening here is an addition of two binary values from a
memory address to another memory address or register, as defined in
the language specification for the "+=" operator.
One of which may be a trap representation for the type...
I can imagine a system where the compiler or the architecture causes a
program using an uninitialised variable to abort or cast an exception /
interrupt etc. if thats what you mean then agreed, than can happen, but
I don't think its a good idea.


Stop and think. There may exist bit patterns that are invalid (trap
representation) for a certain type, even if they are perfectly valid
for some other type. Your `data` array, which I believe is of type that
may have trap representation( s), may have been allocated the space
containing just such bit pattern (e.g. from previous use by `unsigned
char` which cannot have trap values, padding bits notwithstanding ).

--
BR, Vladimir

Mar 16 '06 #35
tom fredriksen wrote:
Chris Dollin wrote:
tom fredriksen wrote:
>>> total += data[c]


Explain to me how this statement causes undefined behaviour


/because the standard says so/.

Really. If `data[c]` has not been given a value (in a way sanctioned
by the standard), then the Standard says that all bets are now off,
it can't say anthing about the future behavior of the code.

That's all that "undefined behaviour" means (according to the C
standard). It means that the Standard doesn't specify the future
behaviour of the code - it's not defined, it's un-defined, the
implementation is at liberty to prescribe the behaviour in any
way it likes without fear of contradiction.
and how its
behaviour will be different on different architectures.
It will be different if the architecture, or the implementation,
says so.
The difference here is whether data[c] has a value set by me instead of
a random value from some historic use of that memory address.
Well, no. The difference is that the implementation can do what it
likes. It could arrange to set all the elements to 0, or -1, or
0xdeadbeef, or __TRAP before you access it. The implementation
could arrange that the array is given its own memory segment
without read access, and only grant read access when at least
one write has been given. The compiler could spot that you'll
accessed uninitialised memory and, just before you do so, plant
code:

puts( "you were going to read uninitialised memory!" );
exit( 17 );
The only thing happening here is an addition of two binary values from a
memory address to another memory address or register, as defined in
the language specification for the "+=" operator.
.... which says that anything is allowed to happen at this point.
I can imagine a system where the compiler or the architecture causes a
program using an uninitialised variable to abort or cast an exception /
interrupt etc. if thats what you mean
It's one of the things that is /permitted/.
then agreed, than can happen, but I don't think its a good idea.


But people who think it /is/ a good idea can use implementations
that /do/ do it, and those implementations are conformant (in that
respect).

Myself, I'd like to be /able/ to use an implementation that spots
bad reads and bad writes; it's nice to know I'm allowed to.

--
Chris "sparqling" Dollin
"Who do you serve, and who do you trust?"
Mar 16 '06 #36
Chris Dollin wrote:
tom fredriksen wrote:
Chris Dollin wrote:
tom fredriksen wrote:
>>> total += data[c]
Explain to me how this statement causes undefined behaviour


It will be different if the architecture, or the implementation,
says so.


Thats not really an argument, its just a contradiction. Please give an
factual example how it can cause undefined behaviour.
The difference here is whether data[c] has a value set by me instead of
a random value from some historic use of that memory address.
Well, no. The difference is that the implementation can do what it
likes. It could arrange to set all the elements to 0, or -1, or
0xdeadbeef, or __TRAP before you access it.

What is a __TRAP on f.ex an x86 or a ppc? In the eyes of a cpu which
deals with 32 bit integers datatypes, just another 32 bit value.
The implementation
could arrange that the array is given its own memory segment
without read access, and only grant read access when at least
one write has been given. The compiler could spot that you'll
accessed uninitialised memory and, just before you do so, plant
code:

puts( "you were going to read uninitialised memory!" );
exit( 17 );


Could you point me to any system that does anything like this for the
given example?

/tom
Mar 16 '06 #37
tom fredriksen wrote:
Chris Dollin wrote:
tom fredriksen wrote:
Chris Dollin wrote:
tom fredriksen wrote:
>>> total += data[c]

Explain to me how this statement causes undefined behaviour
It will be different if the architecture, or the implementation,
says so.


Thats not really an argument, its just a contradiction.


It's not a contradiction. Look, you're asking the wrong question:
how could it happen on some machine? /It doesn't matter./ What
matters is that the behaviour is not constrained by the standard;
the implementation is free to choose what to do.
Please give an
factual example how it can cause undefined behaviour.
You seem to think that "undefined behaviour" is something specific.
It isn't. /Defined/ behaviour is specific. The "cause" of undefined
behaviour is doing something that the standard says produces
undefined behaviour.
The difference here is whether data[c] has a value set by me instead of
a random value from some historic use of that memory address.


Well, no. The difference is that the implementation can do what it
likes. It could arrange to set all the elements to 0, or -1, or
0xdeadbeef, or __TRAP before you access it.


What is a __TRAP on f.ex an x86 or a ppc?


Whatever the implementation says it is (if it exists).
In the eyes of a cpu which
deals with 32 bit integers datatypes, just another 32 bit value.


[Just in passing ... your data array was an `int`, right? So it can be
a 16-bit integer, not a 32-bit one.]

Or just another 64-bit value with 32 value bits, 31 padding bits,
and a single "unassigned " bit set and read appropriately. Slower,
less compact, but handy for debugging.
The implementation
could arrange that the array is given its own memory segment
without read access, and only grant read access when at least
one write has been given. The compiler could spot that you'll
accessed uninitialised memory and, just before you do so, plant
code:

puts( "you were going to read uninitialised memory!" );
exit( 17 );


Could you point me to any system that does anything like this for the
given example?


No. Does that matter? Won't you believe that that latitude is granted
without a system to hand that actually exploits it?

[A quick Google suggests that running under Valgrind or Saber-C would
come plausibly close.]

A final note: if `data[]` is uninitialised, `total += data[c]` might
very easily overflow, if the pseudo-random values left lying around
inside [if that's what happened] were big enough. In which case, you
have another cause of undefined behaviour ...

--
Chris "sparqling" Dollin
"Who do you serve, and who do you trust?"
Mar 16 '06 #38
Chris Dollin wrote:
. . .
A final note: if `data[]` is uninitialised, `total += data[c]` might
very easily overflow . . .


At last, someone has picked up on what I posted very early in
this thread. Overflow interrupts need to be serviced, and this
consumes extra TIME which, depending on the implementation,
may be charged to the process in which they occurred.
--

Mar 16 '06 #39

Chris Dollin wrote:
You seem to think that "undefined behaviour" is something specific.
It isn't. /Defined/ behaviour is specific. The "cause" of undefined
behaviour is doing something that the standard says produces
undefined behaviour.


No I don't think that. But undefined behaviour in my book is behaviour
not defined, if you tell the computer to do something then its defined.
The compiler controls the undefined behaviour so, therefore its not
undefined anymore, portability or not.

Lets just agree that we to some extent disagree, we have different
viewpoints. I agree that in the standard its undefined, but in my
opinion it is defined because of the above statement.

/tom
Mar 16 '06 #40

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

24
8659
by: Kunal | last post by:
Hello, I need help in removing if ..else conditions inside for loops. I have used the following method but I am not sure whether it has actually helped. Below is an example to illustrate what I have used. Original code : c= 0 ; for (i=0; i<999; i++)
0
10829
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10925
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9640
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
8018
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
7171
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5854
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
6058
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4682
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
4276
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.