Which of the two statements is faster?
Author Message
Which of the two statements is faster?

Which of the two statements is faster?

1)  RECEIV_FIELD = 2 * 4;

2)  DECLARE No_TWO   FIXED BINARY (15) INITIAL (2);
DECLARE No_FOUR  FIXED BINARY (15) INITIAL (4);
RECEIV_FIELD = No_TWO * No_FOUR;

Sent via Deja.com http://www.*-*-*.com/

Sat, 01 Mar 2003 15:25:28 GMT
Which of the two statements is faster?

Quote:

> Which of the two statements is faster?

> 1)  RECEIV_FIELD = 2 * 4;

> 2)  DECLARE No_TWO   FIXED BINARY (15) INITIAL (2);
>     DECLARE No_FOUR  FIXED BINARY (15) INITIAL (4);
>     RECEIV_FIELD = No_TWO * No_FOUR;

trick question. (assuming that *Process Opt(Time) is specified)
1) will just be an assignment.  the 2*4 will be evaluated at compile
time
2) will be a multiply and store the result
now what's the prize - or why did you ask?

Quote:
> Sent via Deja.com http://www.deja.com/

Sent via Deja.com http://www.deja.com/

Sat, 01 Mar 2003 19:38:42 GMT
Which of the two statements is faster?

Quote:

> > Which of the two statements is faster?

> > 1)  RECEIV_FIELD = 2 * 4;

> > 2)  DECLARE No_TWO   FIXED BINARY (15) INITIAL (2);
> >     DECLARE No_FOUR  FIXED BINARY (15) INITIAL (4);
> >     RECEIV_FIELD = No_TWO * No_FOUR;

> trick question. (assuming that *Process Opt(Time) is specified)
> 1) will just be an assignment.  the 2*4 will be evaluated at compile
> time
> 2) will be a multiply and store the result
> now what's the prize - or why did you ask?

This is HEAVILY dependent upon the compiler, upon which optimization levels
are selected, and upon the underlying hardware architecture.  On the Stratus
VOS PL/I Subset G compiler, at the default (highest) optimization level, on
all 3 of our supported hardware architectures, these two assignment
statements are essentially equal. The following program:

test_compiler:
procedure;

declare no_two           fixed binary (15) static initial (2);
declare no_four          fixed binary (15) static initial (4);
declare receiv_field1    fixed binary (15);
declare receiv_field2    fixed binary (15);

receiv_field1 = 2 * 4;
receiv_field2 = no_two * no_four;

put list (receiv_field1, receiv_field2);
put skip;

end test_compiler;

generates the equivalent of:

store the register into receiv_field1
store the register into receiv_field2

Even if you are using a compiler that does not do common subexpression
elimination, constant folding, and global flow optimizations, as ours does
(to name but a few of its optimizations), even if the statements are
compiled naively, leaving in the multiplication, as long as you are running
on a modern (say, post 1990) RISC architecture processor, I claim that the
cost of the multiply will disappear into the RISC optimizations.  In most
RISC architectures, the register-to-register instructions are basically
free. You are paying for the costs of the loads and the stores; especially
ones that cause CPU cache misses, and far far worse for references to
globally shared writeable data.  We're talking orders of magnitude
difference between the cost of the multiply and the cost of storing the
result into a location that is modified, not in the local cache, but in the
cache of another CPU.

I could give a similar lecture about algorithms.

The bottom line, IMNSHO, is that if you are busy worrying about the relative
performance differences in these two coding styles, your knowledge is way
out-of-date and you are focusing on the wrong problem.  Write clear,
Have a consistent "house" style. Learn from your mistakes; keep a list of
your common errors and then improve your skills so that you don't make them
again.  Focus on the data structures and the algorithms. Use appropriate
data types.  Avoid redundant or repeated code (use functions or subroutines
not the "copy" request in the text editor).  Use a profiler to find hot
spots.  Use code coverage tools to ensure that you have tested all of your
statements.  Run both functional and negative tests. When appropriate, run
stress tests to ensure it works under heavy load.

If you do these things, you will write efficient, maintainable code; and you
will be spending your time efficiently, too.

For some examples of Stratus PL/I programs that show these principles (in
varying degrees of success), please see any file matching "*.pl1" at
ftp://ftp.stratus.com/pub/vos/tools/tools.html.  For example, I wrote a
program to calculate the days remaining until 2000 January 1st; it is
ftp://ftp.stratus.com/pub/vos/tools/days_to_y2k.pl1. I also wrote a program
to remove tabs from files and change them to spaces. See
ftp://ftp.stratus.com/pub/vos/tools/detab.pl1. There are plenty of other
examples in this directory, from multiple authors.

Let me add that I've been writing PL/I code continuously since 1969, and I
use the principles myself, and I had to learn some of them the hard way. (I
had good role models and teachers, fortunately, or I would have had to learn
more of them the hard way).

Thanks
PG
--
Paul Green, Senior Technical Consultant, Stratus Computer.
Day: +1 978-461-7557; Eve: +1 978-456-3547; FAX: +1 978-461-3610
Speaking from Stratus not for Stratus

Sat, 01 Mar 2003 22:11:14 GMT
Which of the two statements is faster?
Paul,
you went to a great deal of trouble - and moved the goal posts
the initial fields are automatic (its not specified)
so why did you change them to static?
RECEIV_FIELD was float - so why change it to fixed?
- - - -
I just want to know why the question was asked at all
- - - -
I would agree wholeheartly with all of your sentiments on programming
Quote:
>I claim that the cost of the multiply will disappear into the RISC

optimizations.
is even more true for the non-RISC IBM copper processors
which executes register to register instruction at the same time
as register to storage (a different register) instructions
so they disappear completely
- - -
when you say
Quote:
>Use code coverage tools to ensure that you have tested all of your

statements
Do you not use flow & count ?
- - - -
best wishes

Quote:

> > > Which of the two statements is faster?

> > > 1)  RECEIV_FIELD = 2 * 4;

> > > 2)  DECLARE No_TWO   FIXED BINARY (15) INITIAL (2);
> > >     DECLARE No_FOUR  FIXED BINARY (15) INITIAL (4);
> > >     RECEIV_FIELD = No_TWO * No_FOUR;

> > trick question. (assuming that *Process Opt(Time) is specified)
> > 1) will just be an assignment.  the 2*4 will be evaluated at compile
> > time
> > 2) will be a multiply and store the result
> > now what's the prize - or why did you ask?

> This is HEAVILY dependent upon the compiler, upon which optimization
levels
> are selected, and upon the underlying hardware architecture.  On the
Stratus
> VOS PL/I Subset G compiler, at the default (highest) optimization
level, on
> all 3 of our supported hardware architectures, these two assignment
> statements are essentially equal. The following program:

> test_compiler:
>      procedure;

> declare no_two           fixed binary (15) static initial (2);
> declare no_four          fixed binary (15) static initial (4);
> declare receiv_field1    fixed binary (15);
> declare receiv_field2    fixed binary (15);

>      receiv_field1 = 2 * 4;
>      receiv_field2 = no_two * no_four;

>      put list (receiv_field1, receiv_field2);
>      put skip;

>      end test_compiler;

> generates the equivalent of:

>      load 8 into a register
>      store the register into receiv_field1
>      store the register into receiv_field2

> Even if you are using a compiler that does not do common subexpression
> elimination, constant folding, and global flow optimizations, as ours
does
> (to name but a few of its optimizations), even if the statements are
> compiled naively, leaving in the multiplication, as long as you are
running
> on a modern (say, post 1990) RISC architecture processor, I claim
that the
> cost of the multiply will disappear into the RISC optimizations.  In
most
> RISC architectures, the register-to-register instructions are
basically
> free. You are paying for the costs of the loads and the stores;
especially
> ones that cause CPU cache misses, and far far worse for references to
> globally shared writeable data.  We're talking orders of magnitude
> difference between the cost of the multiply and the cost of storing
the
> result into a location that is modified, not in the local cache, but
in the
> cache of another CPU.

> I could give a similar lecture about algorithms.

> The bottom line, IMNSHO, is that if you are busy worrying about the
relative
> performance differences in these two coding styles, your knowledge is
way
> out-of-date and you are focusing on the wrong problem.  Write clear,
> structured, easy-to-read code with liberal use of white space and
> Have a consistent "house" style. Learn from your mistakes; keep a
list of
> your common errors and then improve your skills so that you don't
make them
> again.  Focus on the data structures and the algorithms. Use
appropriate
> data types.  Avoid redundant or repeated code (use functions or
subroutines
> not the "copy" request in the text editor).  Use a profiler to find
hot
> spots.  Use code coverage tools to ensure that you have tested all of
your
> statements.  Run both functional and negative tests. When
appropriate, run
> stress tests to ensure it works under heavy load.

> If you do these things, you will write efficient, maintainable code;
and you
> will be spending your time efficiently, too.

> For some examples of Stratus PL/I programs that show these principles
(in
> varying degrees of success), please see any file matching "*.pl1" at
> ftp://ftp.stratus.com/pub/vos/tools/tools.html.  For example, I wrote
a
> program to calculate the days remaining until 2000 January 1st; it is
> ftp://ftp.stratus.com/pub/vos/tools/days_to_y2k.pl1. I also wrote a
program
> to remove tabs from files and change them to spaces. See
> ftp://ftp.stratus.com/pub/vos/tools/detab.pl1. There are plenty of
other
> examples in this directory, from multiple authors.

> Let me add that I've been writing PL/I code continuously since 1969,
and I
> use the principles myself, and I had to learn some of them the hard
way. (I
> had good role models and teachers, fortunately, or I would have had
to learn
> more of them the hard way).

> Thanks
> PG
> --
> Paul Green, Senior Technical Consultant, Stratus Computer.
> Day: +1 978-461-7557; Eve: +1 978-456-3547; FAX: +1 978-461-3610
> Speaking from Stratus not for Stratus

Sent via Deja.com http://www.deja.com/

Sun, 02 Mar 2003 00:36:04 GMT
Which of the two statements is faster?
re: "Elder Lemon's" questions on my earlier reply...

You didn't specify the data type of RECEIV_FIELD in your original posting.
So I picked one, using Occam's Razor. But the data type isn't material to
the optimization, at least in my compiler.

I changed the storage class from automatic to static because PL/I Subset G,
which is the version of the language that the VOS PL/I compiler implements,
does not permit automatic storage to have the initial attribute.  Again,
this is immaterial to the optimization.

The VOS compilers won't even allocate storage (automatic or static) when the
optimizer can determine that the storage is not needed.  In this case, no
storage will be allocated for any of the constant variables; only for the
variables that are passed to the put list statement.

I refer to code coverage generically; the command names that a particular
operating system provides are not all that interesting.

Thanks
PG
--
Paul Green, Senior Technical Consultant, Stratus Computer.
Day: +1 978-461-7557; Eve: +1 978-456-3547; FAX: +1 978-461-3610
Speaking from Stratus not for Stratus

Sun, 02 Mar 2003 03:00:00 GMT
Which of the two statements is faster?
(snip)

Quote:
>> platform: IBM mainframe OS/390
>It might seem strange, but static takes up less storage than antomatic.
>As a general "rule of thumb" for batch programs,
>if a variable has an "init" then make it static
>(on-line reentrant programs can have different considerations)
>if its static, the data exists just once.
>if its automatic (the default), the initial values must exist
>and then PLI acquires the automatic storage and copies the initial
>values, effectively doubling the storage required !
>(and you know how expensive that is just check the price)
>(plus the nano-second required to move the initial values)

But that means that the initial value goes into the load module,
and has to be loaded by program fetch.   Now it gets complicated.
A whole series of variables could get initialized at once this way.
Initializing a large array to a constant value fills the load module
with those constants, though.  Last I knew, non-initialized data
(DS in assembler) didn't go into the load module, but DC does.
The assembler, and I believe the loader, have to start a new record
at every DC/DS boundary.  That may mean a lot of overhead for a single
static init variable.

In a subroutine of function, usually the choice depends on what it
will be used for.

-- glen

Sun, 02 Mar 2003 03:00:00 GMT
Which of the two statements is faster?

Quote:

> > Which of the two statements is faster?

> > 1)  RECEIV_FIELD = 2 * 4;

> > 2)  DECLARE No_TWO   FIXED BINARY (15) INITIAL (2);
> >     DECLARE No_FOUR  FIXED BINARY (15) INITIAL (4);
> >     RECEIV_FIELD = No_TWO * No_FOUR;

> trick question. (assuming that *Process Opt(Time) is specified)
> 1) will just be an assignment.  the 2*4 will be evaluated at compile
> time
> 2) will be a multiply and store the result
> now what's the prize - or why did you ask?

I am sorry but there is no special prize, except that great extensive
answer of Paul. (txs Paul! ;)
The reason why I asked this question: I often see that my former
colleagues used to work with fields staticly initiated with a number. I
really wondered why! Didn't they have to deal with less storage, then?
platform: IBM mainframe OS/390

Quote:

> > Sent via Deja.com http://www.deja.com/

> Sent via Deja.com http://www.deja.com/

Sent via Deja.com http://www.deja.com/

Sun, 02 Mar 2003 15:44:44 GMT
Which of the two statements is faster?

Quote:

> > > Which of the two statements is faster?

> > > 1)  RECEIV_FIELD = 2 * 4;

> > > 2)  DECLARE No_TWO   FIXED BINARY (15) INITIAL (2);
> > >     DECLARE No_FOUR  FIXED BINARY (15) INITIAL (4);
> > >     RECEIV_FIELD = No_TWO * No_FOUR;

> > trick question. (assuming that *Process Opt(Time) is specified)
> > 1) will just be an assignment.  the 2*4 will be evaluated at compile
> > time
> > 2) will be a multiply and store the result
> > now what's the prize - or why did you ask?

> I am sorry but there is no special prize, except that great extensive
> answer of Paul. (txs Paul! ;)
> The reason why I asked this question: I often see that my former
> colleagues used to work with fields staticly initiated with a number.
I
> really wondered why! Didn't they have to deal with less storage, then?
> platform: IBM mainframe OS/390

It might seem strange, but static takes up less storage than antomatic.
As a general "rule of thumb" for batch programs,
if a variable has an "init" then make it static
(on-line reentrant programs can have different considerations)
- - -
if its static, the data exists just once.
if its automatic (the default), the initial values must exist
and then PLI acquires the automatic storage and copies the initial
values
effectively doubling the storage required !
(and you know how expensive that is just check the price)
(plus the nano-second required to move the initial values)
;)
- - -

Quote:

> > > Sent via Deja.com http://www.deja.com/
> > > Before you buy.

> > Sent via Deja.com http://www.deja.com/

> Sent via Deja.com http://www.deja.com/

Sent via Deja.com http://www.deja.com/

Sun, 02 Mar 2003 17:31:04 GMT
Which of the two statements is faster?
For OS (MVS or OS/390) consider a program call GOODPGM.
In the final executable CSECT GOODPGM1 will contain the
executable code (instructions) and CSECT GOODPGM2 will
contain the STATIC storage.  We can see that initialised STATIC
corresponds to Assembler DC (Define Constant) while uninitialised
STATIC corresponds to Assembler DS (Define Storage).

While DS needs less space in the object "deck" (no TXT record(s)
are required) than DC, for the final output the binder (and the
linkage editor if you still use that) still writes the storage (usually
nulls) for DS data in a CSECT.

Thus there is no penalty in load module or program object size
in initialising STATIC storage.  Indeed, there could be a benefit
because you can then avoid assignment statements.

AUTOMATIC storage could be initialised by program logic rather
than DCL statements.  Simple saying A= 0; can initialise a whole
array or structure to zeros (blanks for the character elements of
a structure - automatically processed by the compiler) in code
smaller than the data size.

Note that STATIC variables which are updated by the program
should not be used for reentrant programs.

I look forward to the promulgation of the VALUE DCL type which
is like an Assembler EQU (equate).  I <think> this has made it to
the OS/390 Visual Age PL/I compiler.

Cheers,
Greg Price

Quote:

> (snip)
> >> platform: IBM mainframe OS/390

> >It might seem strange, but static takes up less storage than antomatic.
> >As a general "rule of thumb" for batch programs,
> >if a variable has an "init" then make it static
> >(on-line reentrant programs can have different considerations)

> >if its static, the data exists just once.
> >if its automatic (the default), the initial values must exist
> >and then PLI acquires the automatic storage and copies the initial
> >values, effectively doubling the storage required !
> >(and you know how expensive that is just check the price)
> >(plus the nano-second required to move the initial values)

> But that means that the initial value goes into the load module,
> and has to be loaded by program fetch.   Now it gets complicated.
> A whole series of variables could get initialized at once this way.
> Initializing a large array to a constant value fills the load module
> with those constants, though.  Last I knew, non-initialized data
> (DS in assembler) didn't go into the load module, but DC does.
> The assembler, and I believe the loader, have to start a new record
> at every DC/DS boundary.  That may mean a lot of overhead for a single
> static init variable.

> In a subroutine of function, usually the choice depends on what it
> will be used for.

> -- glen

Mon, 03 Mar 2003 03:00:00 GMT
Which of the two statements is faster?

Quote:

>For OS (MVS or OS/390) consider a program call GOODPGM.
>In the final executable CSECT GOODPGM1 will contain the
>executable code (instructions) and CSECT GOODPGM2 will
>contain the STATIC storage.  We can see that initialised STATIC
>corresponds to Assembler DC (Define Constant) while uninitialised
>STATIC corresponds to Assembler DS (Define Storage).
>While DS needs less space in the object "deck" (no TXT record(s)
>are required) than DC, for the final output the binder (and the
>linkage editor if you still use that) still writes the storage (usually
>nulls) for DS data in a CSECT.

There was a discussion of this, I believe in IBM-MAIN, and I thought

-- glen

Mon, 03 Mar 2003 03:00:00 GMT
Which of the two statements is faster?
Technically, "2" and "4" are FIXED DECIMAL constants.  Presumably a
stupid compiler could multiply 2 * 4 to get a FIXED DECIMAL result, then
convert it to FIXED BINARY in assigning it to "result".  I doubt that
very many compilers would do this.
Quote:

> > > Which of the two statements is faster?

> > > 1)  RECEIV_FIELD = 2 * 4;

> > > 2)  DECLARE No_TWO   FIXED BINARY (15) INITIAL (2);
> > >     DECLARE No_FOUR  FIXED BINARY (15) INITIAL (4);
> > >     RECEIV_FIELD = No_TWO * No_FOUR;

> > trick question. (assuming that *Process Opt(Time) is specified)
> > 1) will just be an assignment.  the 2*4 will be evaluated at compile
> > time
> > 2) will be a multiply and store the result
> > now what's the prize - or why did you ask?

> I am sorry but there is no special prize, except that great extensive
> answer of Paul. (txs Paul! ;)
> The reason why I asked this question: I often see that my former
> colleagues used to work with fields staticly initiated with a number. I
> really wondered why! Didn't they have to deal with less storage, then?
> platform: IBM mainframe OS/390

Tue, 04 Mar 2003 03:00:00 GMT
Which of the two statements is faster?

Quote:
> Technically, "2" and "4" are FIXED DECIMAL constants.  Presumably a
> stupid compiler could multiply 2 * 4 to get a FIXED DECIMAL result, then
> convert it to FIXED BINARY in assigning it to "result".  I doubt that
> very many compilers would do this.

The Stratus VOS PL/I compiler has done this sort of optimization (and many
other similar "constant folding" operations) for years.  And yes, we follow
all appropriate PL/I language rules, and we retain full precision.  So, why
do you call a compiler that does this "stupid"?  Have you ever tried writing
the code to do this?  It isn't a simple problem.

PG
--
Paul Green, Senior Technical Consultant, Stratus Computer.
Day: +1 978-461-7557; Eve: +1 978-456-3547; FAX: +1 978-461-3610
Speaking from Stratus not for Stratus

Tue, 04 Mar 2003 03:00:00 GMT
Which of the two statements is faster?

Quote:

> > Technically, "2" and "4" are FIXED DECIMAL constants.  Presumably a
> > stupid compiler could multiply 2 * 4 to get a FIXED DECIMAL result,
then
> > convert it to FIXED BINARY in assigning it to "result".  I doubt
that
> > very many compilers would do this.

> The Stratus VOS PL/I compiler has done this sort of optimization (and
many
> other similar "constant folding" operations) for years.  And yes, we
follow
> all appropriate PL/I language rules, and we retain full precision.
So, why
> do you call a compiler that does this "stupid"?  Have you ever tried
writing
> the code to do this?  It isn't a simple problem.

> PG
> --
> Paul Green, Senior Technical Consultant, Stratus Computer.
> Day: +1 978-461-7557; Eve: +1 978-456-3547; FAX: +1 978-461-3610
> Speaking from Stratus not for Stratus

Paul,
I'm sure that Peter didn't mean to call your compiler 'stupid'
I suggest that his issue was between decimal arithmetic and binary
arithmetic
All chips support binary arithmetc, Some support decimal arithemetc,
all well.
Others emulate it with microcode.  Others only support binary & the
compilers have to emulate it.
The expression being discussed was:
RECEIV_FIELD = 2 * 4;
Peter said that "Technically, "2" and "4" are FIXED DECIMAL constants."
So you could do a decimal (rather than a binary) multiply
and convert the result to binary
-                  - -
- - -
I had thought that your compiler treated the 2 and 4 as binary
and would do a binary multiply on them
???

Sent via Deja.com http://www.deja.com/

Fri, 07 Mar 2003 03:00:00 GMT
Which of the two statements is faster?
You misinterpreted what I was saying, or I wasn't clear.
I was saying a "stupid" compiler whould generate the same code whether
constants or variables were involved.  A more intelligent compiler
would, like yours, evaluate constant expressions at compile time.

In answer to your question, yes, I'm working on it now.  With PL/I,
NOTHING is a simple problem, but this is far from the most difficult.

Quote:

> > Technically, "2" and "4" are FIXED DECIMAL constants.  Presumably a
> > stupid compiler could multiply 2 * 4 to get a FIXED DECIMAL result,
then
> > convert it to FIXED BINARY in assigning it to "result".  I doubt
that
> > very many compilers would do this.

> The Stratus VOS PL/I compiler has done this sort of optimization (and
many
> other similar "constant folding" operations) for years.  And yes, we
follow
> all appropriate PL/I language rules, and we retain full precision.
So, why
> do you call a compiler that does this "stupid"?  Have you ever tried
writing
> the code to do this?  It isn't a simple problem.

> PG
> --
> Paul Green, Senior Technical Consultant, Stratus Computer.
> Day: +1 978-461-7557; Eve: +1 978-456-3547; FAX: +1 978-461-3610
> Speaking from Stratus not for Stratus

Sent via Deja.com http://www.deja.com/