Author Topic: All variables should be Global  (Read 18097 times)

0 Members and 1 Guest are viewing this topic.

Offline cyberfish

  • Regular Contributor
  • *
  • Posts: 240
  • Country: gb
Re: All variables should be Global
« Reply #25 on: February 28, 2017, 05:47:52 pm »
Nested functions are available in GCC as a extension.

It has been available in C++ since C++11 though!

As if C++ was not a deep enough quagmire of features ready to drown yourself in!

It's a difficult language to learn, but once you are proficient with it it's amazing!

You get all the performance benefits of C (sometimes even faster than C from things like template meta-programming), with high level constructs that save a lot of time/code.
 

Offline Sal Ammoniac

  • Super Contributor
  • ***
  • Posts: 1672
  • Country: us
Re: All variables should be Global
« Reply #26 on: February 28, 2017, 06:10:06 pm »
It has been available in C++ since C++11 though!

With incredibly painful syntax that only a demented language designer could love.  :palm:
Complexity is the number-one enemy of high-quality code.
 

Offline Cerebus

  • Super Contributor
  • ***
  • Posts: 10576
  • Country: gb
Re: All variables should be Global
« Reply #27 on: February 28, 2017, 06:38:24 pm »
With incredibly painful syntax that only a demented language designer could love.  :palm:

I don't think any actual design was involved.

If you think that syntax is painful to use or remember, try writing a parser for it - the actual grammar is about as irregular and inconsistent as you can get without actually deliberately setting out to make it that way.
Anybody got a syringe I can use to squeeze the magic smoke back into this?
 

Offline grumpydoc

  • Super Contributor
  • ***
  • Posts: 2905
  • Country: gb
Re: All variables should be Global
« Reply #28 on: February 28, 2017, 06:56:30 pm »
Nested functions are available in GCC as a extension.

It has been available in C++ since C++11 though!

As if C++ was not a deep enough quagmire of features ready to drown yourself in!

It's a difficult language to learn, but once you are proficient with it it's amazing!

As a professional software engineer I have written a lot of C++ although I am a bit out of touch with some of the newer language features including lambda expressions. EDIT: I left full-time IT in 2003. I just tinker these days.

As a software developer I agree that it is a nice language to work with, it is expressive and nuanced and you can write elegant code if you wish.

With a more managerial hat on, however, I grew more and more disillusioned with the language - the more large projects are tempted to use the "neat" features of the language (especially templates and now, I suppose, lambdas) the more they become difficult to maintain and the bar to new staff joining a project becomes ever higher. Large, complex C++ programs can be impossible to comprehend because they simply defeat static analysis.

I think part of the problem is that the C++ committee likes to add "powerful building blocks" to the language but forget that these features need a very responsible hand when in use. The nested functions thing is a case in point - rather than add nested functions they chose to add lambda bindings sufficiently powerful to allow them to be used to implement nested functions. Templates is another example - did you realise that the template language is actually Turing complete and there are examples of code which causes the compiler to emit (eg) Fibonacci sequences or lists of prime numbers as a side effect of compilation. I mean, did we really need that  |O

These days I actually prefer well crafted C
« Last Edit: February 28, 2017, 07:40:33 pm by grumpydoc »
 

Offline cyberfish

  • Regular Contributor
  • *
  • Posts: 240
  • Country: gb
Re: All variables should be Global
« Reply #29 on: February 28, 2017, 07:08:26 pm »
It has been available in C++ since C++11 though!

With incredibly painful syntax that only a demented language designer could love.  :palm:

Yeah. That's because lambda expressions are much more useful than just for nested functions.

It also allows you to pass those functions around as objects, and bind local values and references to them. That makes async code much cleaner.

When used as nested functions, the syntax does seem over-engineered.

Quote
I think part of the problem is that the C++ committee likes to add "powerful building blocks" to the language but forget that these features need a very responsible hand when in use.
This I totally agree with. It's one of the main differences in design philosophy between Java and C++. Java = don't include features that can be abused. C++ = include features as long as there are uses for them.

This is why we don't have operator overloading in Java for example (very useful if used correctly, but easy to abuse), and we still have goto in C++ (can be used to break out of nested loops, which would otherwise require a bunch of flags, or abusing exceptions). I would much rather work in C++ than Java, but I would much rather work with an incompetent Java developer than an incompetent C++ one.

Luckily everyone I work with are highly competent, so I don't worry about that too much.
 

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 19508
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: All variables should be Global
« Reply #30 on: February 28, 2017, 07:38:40 pm »
Nested functions are available in GCC as a extension.

It has been available in C++ since C++11 though!

As if C++ was not a deep enough quagmire of features ready to drown yourself in!

It's a difficult language to learn, but once you are proficient with it it's amazing!

As a professional software engineer I have written a lot of C++ although I am a bit out of touch with some of the newer language features including lambda expressions.

As a software developer I agree that it is a nice language to work with, it is expressive and nuanced and you can write elegant code if you wish.

With a more managerial hat on, however, I grew more and more disillusioned with the language - the more large projects are tempted to use the "neat" features of the language (especially templates and now, I suppose, lambdas) the more they become difficult to maintain and the bar to new staff joining a project becomes ever higher. Large, complex C++ programs can be impossible to comprehend because they simply defeat static analysis.

I think part of the problem is that the C++ committee likes to add "powerful building blocks" to the language but forget that these features need a very responsible hand when in use. The nested functions thing is a case in point - rather than add nested functions they chose to add lambda bindings sufficiently powerful to allow them to be used to implement nested functions. Templates is another example - did you realise that the template language is actually Turing complete and there are examples of code which causes the compiler to emit (eg) Fibonacci sequences or lists of prime numbers as a side effect of compilation. I mean, did we really need that  |O

These days I actually prefer well crafted C

All very very true, unfortunately :(

In the early 90s I decided that "if C++ is the answer, then you ought to change the question". Unfortunately nothing has caused me to change that somewhat aesthetic decision. Back then the two key points for me were
  • the template language "features" you mention, because they were discovered and the design committee did not believe it until someone rubbed their noses in it. I prefer my tools to be designed, not discovered
  • the endless discussions as to whether it "casting away constness" should be mandatory or should be forbidden

Much later, the amusing/frightening C++ FQA emerged. Anybody contemplating using C++ should understand its ramifications inside out before using the language.
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 

Offline hans

  • Super Contributor
  • ***
  • Posts: 1640
  • Country: nl
Re: All variables should be Global
« Reply #31 on: February 28, 2017, 08:13:34 pm »
I thought it would be nice to benchmark said claims on 2 architectures: PIC24 and PIC32.
I chose these because they have simulators in MPLAB X. And both chips have GCC-based compilers.

Also interesting is the contrast between both architectures. The PIC24 has it's CPU registers mapped onto the address bus, and some instructions can access RAM (even like INC [W14], [W14]). However most ALU instructions need to go through the register file.
The PIC32, like ARM CPUs, needs more explicit instructions to access RAM. Mainly via pointers only.

Now, let's run this code:
Code: [Select]
#include <stdint.h>
#include <xc.h>

uint16_t gx = 0;
uint16_t gy = 0;

uint16_t result = 0;
uint32_t s = 0;

inline void doStuffWithGlobals(void)
{
    result = (gx%9) * (gy%3);
}
inline uint32_t doStuffWithParameters(uint16_t x, uint16_t y)
{
    return (x%9) * (y%3);
}

uint32_t benchmarkParams(void)
{
    uint16_t x,y;
    uint32_t r = 0;
    for (y = 0; y < 0xFF; y++)
    {
        for (x = 0; x < 0xFF; x++)
        {
            r += doStuffWithParameters(x,y);
        }
    }
    return r;
}

void benchmarkGlobals(void)
{
    for (gy = 0; gy < 0xFF; gy++)
    {
        for (gx = 0; gx < 0xFF; gx++)
        {
            doStuffWithGlobals();
            s += result;
        }
    }
}

void stopwatchStart(void)
{
    T2CON = 0;
    T2CONbits.T32 = 1;
    TMR2 = 0;
    TMR3 = 0;
    T2CONbits.TON = 1;
}
uint32_t stopwatchStop(void)
{
    T2CONbits.TON = 0;
    return ((uint32_t)TMR2) | ((uint32_t)TMR3 << 16);
}

int main(void)
{
    volatile uint32_t timeParams  = 0;
    volatile uint32_t timeGlobals = 0;
   
    stopwatchStart();
   
    volatile uint32_t s1 = benchmarkParams();
   
    timeParams = stopwatchStop();
   
    stopwatchStart();
    benchmarkGlobals();
   
    volatile uint32_t s2 = s;
   
    timeGlobals = stopwatchStop();
   
    // s1 should be s2
    while(1);
}

In all cases the computed result is correct. The algorithm I try to benchmark is just some bogus thing, but at least the compiler isn't clever enough to optimize away the complete algorithm straight away.

For PIC24 I used XC16 1.30 GCC -O1 + "do not override inline".
With inline: Time of parameters: 1,762,339 ticks Time of globals: 1,761,832 ticks
Without inline: Parameters: 3,772,759 Globals: 4,097,871

If I change the algorithm to simply x*y I get (with inline):
Parameters: 456,727 Globals: 456,476
Without inline: Parameters: 1,889,837 Globals: 1,889,578

Actually quite surprising results. The code actually marginally faster. Now that's cool I suppose, but it's not faster in all cases. Especially on non-optimized code like without inline.
The reason I did not want to focus on x*y though, is because the compiler sees that sequence of operations and optimizes multiplication out of the code. It's not far off from assigning a fixed value to the result.

On PIC32 the results are drastically different:
(XC32 1.30 GCC -O1 -finline-functions)
Inline: Parameters: 848,916 Globals: 978,200
No inline: Parameters: 848,916 Globals: 2,342,448
Multiplication (inline): Parameters: 327,171 Globals: 391,447

Implicit vs explicit compiler optimizations become very clear at this level (the compiler tried to inline the parameterized function anyway). It also shows that RAM access with huge address spaces is a lot more expensive.

That's why they have register files and caches to speed programs up.
 
The following users thanked this post: thm_w

Offline moz

  • Regular Contributor
  • *
  • Posts: 89
  • Country: au
Re: All variables should be Global
« Reply #32 on: February 28, 2017, 09:37:30 pm »
The rule of thumb I use is that good code is more than 90% maintenance. Only bad code is less... it means no-one is using it, or no-one is willing to risk modifying it.

Much later, the amusing/frightening C++ FQA emerged. Anybody contemplating using C++ should understand its ramifications inside out before using the language.

This. I started a project with some specific feature requirements that at the time could really only be met by C++ (talking to embedded hardware via internet-exposed encrypted IP). Sadly Scala, Rust and Go were all 90% there. C++ is awesome, whenever there's a question of features they settle for "all of them". You can do just about anything with the language. Which makes it a bit too much like Perl for my liking - it's very easy to produce write-only code. And the lack of a first class unit test framework makes me cringe.

I have ended up writing "C++ lite" most of the time. No Boost, very few templates, but I use selected features like lambdas a lot because coming down from a modern language it's very hard not to think in lambdas.
 

Offline snarkysparky

  • Frequent Contributor
  • **
  • Posts: 414
  • Country: us
Re: All variables should be Global
« Reply #33 on: February 28, 2017, 09:46:45 pm »

 
On PIC32 the results are drastically different:
(XC32 1.30 GCC -O1 -finline-functions)
Inline: Parameters: 848,916 Globals: 978,200
No inline: Parameters: 848,916 Globals: 2,342,448
Multiplication (inline): Parameters: 327,171 Globals: 391,447

Implicit vs explicit compiler optimizations become very clear at this level (the compiler tried to inline the parameterized function anyway). It also shows that RAM access with huge address spaces is a lot more expensive.

That's why they have register files and caches to speed programs up.


Any speculation as to why globals took so much more time without inlining?
 

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 19508
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: All variables should be Global
« Reply #34 on: February 28, 2017, 10:05:33 pm »
The rule of thumb I use is that good code is more than 90% maintenance. Only bad code is less... it means no-one is using it, or no-one is willing to risk modifying it.

Much later, the amusing/frightening C++ FQA emerged. Anybody contemplating using C++ should understand its ramifications inside out before using the language.

This. I started a project with some specific feature requirements that at the time could really only be met by C++ (talking to embedded hardware via internet-exposed encrypted IP). Sadly Scala, Rust and Go were all 90% there. C++ is awesome, whenever there's a question of features they settle for "all of them". You can do just about anything with the language. Which makes it a bit too much like Perl for my liking - it's very easy to produce write-only code. And the lack of a first class unit test framework makes me cringe.

I have ended up writing "C++ lite" most of the time. No Boost, very few templates, but I use selected features like lambdas a lot because coming down from a modern language it's very hard not to think in lambdas.

That's all valid.

A problem can be that each project and/or developer and/library implicitly chooses a different subset, and they don't play well with each other.

Of course some subsets of some languages have significant tooling and momentum, e.g. MISRA C and SPARK ADA.
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 

Offline TNorthover

  • Contributor
  • Posts: 42
  • Country: us
Re: All variables should be Global
« Reply #35 on: February 28, 2017, 10:12:14 pm »
Any speculation as to why globals took so much more time without inlining?

The test looks simple enough that (with MIPS's 32ish registers) virtually nothing would have to be stored to perform the calculation. Parameters automatically live in registers with or without inlining, so there's no barrier there.

But for globals you need to calculate their address and be store/load them at each function boundary. With inlining, the compiler can remove all the paired load/store operations because it sees them in the same function. Without, no such luck.
 

Offline hans

  • Super Contributor
  • ***
  • Posts: 1640
  • Country: nl
Re: All variables should be Global
« Reply #36 on: February 28, 2017, 10:55:20 pm »
I took a look at the disassembly. GCC dares to inline the multiplication routine even at level O1 and no explicit inline statements. It only does  that with globals at level O2. At O2, you get the same results as with explicit inline. Eventually the compiler does get to a similar level of performance.
However, by nature of a global, the compiler is more careful with optimizing at lower aggressive levels. Perhaps there also situations where a piece of code written using globals doesn't get the 'special treatment'.

This is indeed a really simple algorithm. Not a lot of data is being passed around. A lot of time is crunched in the inner loop. I suppose that the globals wins out because y only changes once every 256 inner loop ticks. For a global call it doesn't have to move the y value explicitly. This could save some time, but in respect to inline it's almost neglible. But that's only 1 case, maybe some others are different. But it certainly is not a general notion to take note of.

To be honest I'm surprised that the compiler isn't able to optimize my little bogus routine to an integer value.

These days in C++ you can generate complete random mazes at compile runtime, perform pathfinding algorithms on them, format the grid, and display it. And it all compiles back to down a const string.
https://youtu.be/3SXML1-Ty5U
 

Offline moz

  • Regular Contributor
  • *
  • Posts: 89
  • Country: au
Re: All variables should be Global
« Reply #37 on: February 28, 2017, 11:19:57 pm »
A problem can be that each project and/or developer and/library implicitly chooses a different subset, and they don't play well with each other.

That's another reason I chose C++, my coworkers at least use C on the embedded side so my code is fairly readable for them. It also means that the data structures look quite similar on both ends of the comms channel ("again with the debugging. Always with you the debugging" in my best Jewish mother-in-law voice).
 

Offline moz

  • Regular Contributor
  • *
  • Posts: 89
  • Country: au
Re: All variables should be Global
« Reply #38 on: February 28, 2017, 11:33:22 pm »
To be honest I'm surprised that the compiler isn't able to optimize my little bogus routine to an integer value.

Do you have access to a library common across architectures? I'm thinking of something like crypto or FFT. That way you can pick one function, hack a version to use mostly globals, and compare.

I have a wee crypto library (TinyAES) that I use for testing because it's all in C rather than the hand-optimised OpenSSL code that is much faster but makes debugging tools really unhappy (valgrind says it uses un-initialised values, OpenSSL say it only looks that way. Etc). But it's complex enough that I can compare real-ish performance just by saying "AES128 this" and get an idea of CPU performance in 10 lines of (my) code.

It also depends on which C complier you're using, and which C standard. C99 at least lets you have local static variables, which are better than globals for reasoning about the code (whether it's you or the compiler doing the reasoning). C11 adds thread-local variables and static asserts, again making life easier. But also making the "everything global" claim even less credible.
 

Offline cyberfish

  • Regular Contributor
  • *
  • Posts: 240
  • Country: gb
Re: All variables should be Global
« Reply #39 on: March 01, 2017, 12:41:11 am »
In the early 90s I decided that "if C++ is the answer, then you ought to change the question". Unfortunately nothing has caused me to change that somewhat aesthetic decision. Back then the two key points for me were
  • the template language "features" you mention, because they were discovered and the design committee did not believe it until someone rubbed their noses in it. I prefer my tools to be designed, not discovered
  • the endless discussions as to whether it "casting away constness" should be mandatory or should be forbidden

Much later, the amusing/frightening C++ FQA emerged. Anybody contemplating using C++ should understand its ramifications inside out before using the language.

"If C++ is the answer, the problem is too complicated for someone who only writes C."

I hope you are aware that the first C++ standard was published in 1998 (so what you looked at wasn't even the first revision), and there has been 3 more standards since, and C++ today is nothing like C++ back then? It's very different even from C++03 (the latest standard before 2011).

For example, (almost) no one does manual memory management anymore. I work as a professional C++ developer and I haven't written any "new" or "delete" in many months. There's also automatic type inference now, saving people a lot of typing.

I'm not sure what the source of a feature has to do with anything. I evaluate language features by their merit. If a good feature was proposed by a random ganster on the streets, I would want it to be added, too.

Templates have their problems, but we don't know any better way to achieve the same, and it's so useful that even Java copied it (and then bastardized it, but that's another discussion).
 

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 19508
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: All variables should be Global
« Reply #40 on: March 01, 2017, 01:05:59 am »
In the early 90s I decided that "if C++ is the answer, then you ought to change the question". Unfortunately nothing has caused me to change that somewhat aesthetic decision. Back then the two key points for me were
  • the template language "features" you mention, because they were discovered and the design committee did not believe it until someone rubbed their noses in it. I prefer my tools to be designed, not discovered
  • the endless discussions as to whether it "casting away constness" should be mandatory or should be forbidden

Much later, the amusing/frightening C++ FQA emerged. Anybody contemplating using C++ should understand its ramifications inside out before using the language.
I hope you are aware that the first C++ standard was published in 1998 (so what you looked at wasn't even the first revision), and there has been 3 more standards since, and C++ today is nothing like C++ back then? It's very different even from C++03 (the latest standard before 2011).

I am aware of that.
I started using C in 1982, when there were precisely two books on it.
I started using C++ in 1988, and having been liberated by grokking Smalltalk, I preferred Objective-C.
In the early 90s I kept using C, kept a watching eye on C++'s glacial progress, and was unpleasantly surprised by the standardisation process. As I said, I prefer my tools to be designed, not discovered. ("Oh look, my multimeter also solders wires")

I also like my tools to solve my problem, not be an added problem. "Language lawyers" are far too much part of the C++ ecosystem; they shouldn't be necessary.

Quote
For example, (almost) no one does manual memory management anymore. I work as a professional C++ developer and I haven't written any "new" or "delete" in many months. There's also automatic type inference now, saving people a lot of typing.

Not to anything like the extent possible with a strongly typed modern language.

Remind me, is it possible to "cast away constness" now?

Quote
I'm not sure what the source of a feature has to do with anything. I evaluate language features by their merit. If a good feature was proposed by a random ganster on the streets, I would want it to be added, too.

I don't see how that is relevant to anything I wrote.

Quote
Templates have their problems, but we don't know any better way to achieve the same, and it's so useful that even Java copied it (and then bastardized it, but that's another discussion).

C++ wasn't the first to employ templates. (Old observation: academic papers about C++ refer to other academic papers about C++, whereas those for language X refer to languages X, Y, Z. That's a reflection of the C++ community being too self-absorbed and inward-looking for its own good)

Java templates are a pigs ear due to the requirement for "type erasure" to ensure backward compatibility. Even so, compilers produce comprehensible error messages, and debuggers produce understandable, correct output.

I suspect C# templates are better, but I have no interest in that language/environment.
« Last Edit: March 01, 2017, 01:07:44 am by tggzzz »
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 

Offline cyberfish

  • Regular Contributor
  • *
  • Posts: 240
  • Country: gb
Re: All variables should be Global
« Reply #41 on: March 01, 2017, 01:26:50 am »
Remind me, is it possible to "cast away constness" now?
Yes, and it has been the case since the very first standard, so I'm not sure why you added the word "now".

Quote
Quote
I'm not sure what the source of a feature has to do with anything. I evaluate language features by their merit. If a good feature was proposed by a random ganster on the streets, I would want it to be added, too.

I don't see how that is relevant to anything I wrote.

Quote
the template language "features" you mention, because they were discovered and the design committee did not believe it until someone rubbed their noses in it. I prefer my tools to be designed, not discovered

Unless you literally meant someone wrote a C++ compiler, didn't write code to support templates, and it turned out to magically support templates? (this would be equivalent to your multimeter and soldering example)
 

Offline westfw

  • Super Contributor
  • ***
  • Posts: 4199
  • Country: us
Re: All variables should be Global
« Reply #42 on: March 01, 2017, 01:54:47 am »
The idea that variables on a stack are less efficient to access if they're on a stack than if they're global is just ... wrong.
Consider "i += 1; // increment variable."

on AVR:
Code: [Select]
  ;; globals:
   lds r16, i    ; load from global: 4 bytes, 2 cycles
   subi r16, -1 ; increment:  2 bytes, 1 cycle
   sts r16, i   ; store to global: 4 bytes, 2 cycles
   
  ;; locals
   ldd r16, Y+i   ; load from stack: 2 bytes, 2 cycles
   subi r16, -1
   std r16, Y+i   ;store to stack: 2 bytes, 2 cycles.


67% bigger to access i as a global.  Z80, 68xx, 6502 all have some form of indexed addressing and should end up using similar code.

It's 100% bigger on an ARM, because there's no LDS equivalent:
Code: [Select]
;; Global
   ldr     r3, [pc, #8]    ; get address of i (6 bytes!)
   ldrb    r2, [r3, #0]    ;  get i
   adds    r2, #6          ; add
   strb    r2, [r3, #0]    ; store

;; local
   ldr     r3, [sp, #4]
   adds    r3, #6
   str     r3, [sp, #4] 

PIC16f might be able to do the global in 2 instructions, but the compiler I tried implemented the "local variable" version as a global anyway.  PIC18 and "enhanced PIC16f15xx" implement some form of indexed addressing, so they get better at handling a stack, even though there is no "hardware stack"  (we remember that stacks are just index registers with some autoincrement/decrement modes, and "stack frames" don't actually need those...)  MSP430 might be able to add immediate values direct to memory, but the instructions start to get long and slow...

And that's without worrying that you need a separate "i" for each subroutine, if you're using globals.

Argument-wise, if your arguments aren't passed in registers (which is common with modern processor) or on the stack, you eventually end up with the (old) BASIC-like syntax where you end up moving your arguments into the correct globals:
Code: [Select]
   sub1_param1=thisval
   sub1_param2=anotherval
   sub1();

(assuming you re-use your subroutines more than once, which ... is part of the idea, you know.)  This is obviously no better than moving the values to the stack (and might be worse, as per the above instructions.)

So, in the absence of an actual example where using globals is more efficient, I claim your entire premise is incorrect!
« Last Edit: March 01, 2017, 02:03:52 am by westfw »
 

Offline snarkysparky

  • Frequent Contributor
  • **
  • Posts: 414
  • Country: us
Re: All variables should be Global
« Reply #43 on: March 01, 2017, 02:24:33 am »
I have read on this issue that if there a many variables needed in a routine then define a struct containing the variables and pass a pointer to it to the function.  Is this a good way to handle many variables.

As an example suppose there is a "motor" datatype created with parameters such as current, speed, voltage, acceleration, temperature...etc.

functions get the pointer to the struct so they can read and modify the values. 

How about if the struct variable is declared with global scope??
 

Offline cyberfish

  • Regular Contributor
  • *
  • Posts: 240
  • Country: gb
Re: All variables should be Global
« Reply #44 on: March 01, 2017, 02:51:31 am »
I have read on this issue that if there a many variables needed in a routine then define a struct containing the variables and pass a pointer to it to the function.  Is this a good way to handle many variables.

As an example suppose there is a "motor" datatype created with parameters such as current, speed, voltage, acceleration, temperature...etc.

functions get the pointer to the struct so they can read and modify the values. 

How about if the struct variable is declared with global scope??

There's no performance difference in this case. Structs (of sizes larger than the largest int type usually) are always passed by pointers anyways (copies are made by caller if necessary).

This is also the sort of basic optimization that any half decent compiler will be able to do, so it's best to just keep the code as clean and intuitive as possible.
 

Offline TNorthover

  • Contributor
  • Posts: 42
  • Country: us
Re: All variables should be Global
« Reply #45 on: March 01, 2017, 03:08:52 am »
There's no performance difference in this case. Structs (of sizes larger than the largest int type usually) are always passed by pointers anyways (copies are made by caller if necessary).

This is roughly true for parameters passed by value (it's very ABI-dependant). But if the routine needs to modify a lot of variables (and so passes disparate values by pointer/reference) I could see putting them together in a struct would be beneficial. You'd possibly save a double-indirection, and the data would be more cache-local if that mattered to you.

Regardless, I'd always recommend making these decisions based on maintainability rather than pure efficiency. At least until there's no other option.

Quote
This is also the sort of basic optimization that any half decent compiler will be able to do, so it's best to just keep the code as clean and intuitive as possible.

Totally agree about the second part, but compilers aren't very free to meddle with parameter passing because functions can usually be called from other files. You need link-time optimization to have a hope in hell, and even then this kind of optimization is most charitably described as an emerging field.
 

Offline cyberfish

  • Regular Contributor
  • *
  • Posts: 240
  • Country: gb
Re: All variables should be Global
« Reply #46 on: March 01, 2017, 03:37:59 am »
Totally agree about the second part, but compilers aren't very free to meddle with parameter passing because functions can usually be called from other files. You need link-time optimization to have a hope in hell, and even then this kind of optimization is most charitably described as an emerging field.
That is true. I'd hope everyone is using LTO by now!

I don't usually pay too much attention to this, because if a function is small enough to be inlined, calling convention doesn't matter anymore. If it isn't, it's probably big enough that call overhead is negligible anyways. Though I guess this is not true if you are highly flash-constrained, and have to optimize for size instead of speed.
 

Online brucehoult

  • Super Contributor
  • ***
  • Posts: 4037
  • Country: nz
Re: All variables should be Global
« Reply #47 on: March 01, 2017, 03:55:39 am »
Any speculation as to why globals took so much more time without inlining?

The test looks simple enough that (with MIPS's 32ish registers) virtually nothing would have to be stored to perform the calculation. Parameters automatically live in registers with or without inlining, so there's no barrier there.

But for globals you need to calculate their address and be store/load them at each function boundary. With inlining, the compiler can remove all the paired load/store operations because it sees them in the same function. Without, no such luck.

Hi Tim, what brings you here from llvm land?

I was a bit confused when you started talking about MIPS when the OP was talking about PIC32. I looked at 8 bit PIC once and ran screaming back to AVR. Didn't realize they'd picked up a decent architecture later. Does it implement the compressed instruction set?
 

Offline TNorthover

  • Contributor
  • Posts: 42
  • Country: us
Re: All variables should be Global
« Reply #48 on: March 01, 2017, 04:12:48 am »
Hi Tim, what brings you here from llvm land?

I decided there'd be even more fun toys to play with if I made them myself. And this specific subforum, just looking to stick my oar in. Good to see you here too!

Quote
Does it implement the compressed instruction set?

I'm afraid I don't know that for certain (my MIPS is strictly theoretical), but Google suggests at least some of them do (https://www.microchip.com/forums/m296546.aspx in particular).
 

Offline T3sl4co1l

  • Super Contributor
  • ***
  • Posts: 21686
  • Country: us
  • Expert, Analog Electronics, PCB Layout, EMC
    • Seven Transistor Labs
Re: All variables should be Global
« Reply #49 on: March 01, 2017, 08:41:22 am »
More examples:

8086:

Code: [Select]
INC BYTE PTR [BP+02]
Instruction: 3 bytes.
Time: 15 + 9 (EA) = 24 cycles.

Code: [Select]
INC BYTE PTR [0002]
Instruction: 4 bytes.
Time: 15 + 6 (EA) = 21 cycles.

Not a big difference, but fairly slow overall.  This is vastly improved in later models (like 386), so the difference is small.  x86 is a very powerful instruction set, but in even later models (highly pipelined, microinstruction, superscalar), the power of that instruction set became a huge burden (i.e., instruction decode takes up a lot of die area, time and power).

Z80:

Code: [Select]
INC (IX+02)
Instruction: 3 bytes.
Time: 6 M-cycles (23 clocks).

Code: [Select]
LD A, (0002)
INC A
LD (0002), A
Instructions: 3+1+3 = 7 bytes.
Time: 9 M-cycles (30 clocks).

There is no INC (nn) instruction (read-modify-write).  With more side-effects, we could also do:

Code: [Select]
LD HL, 0002
INC (HL)
Instructions: 3+1 = 4 bytes.
Time: 6 M-cycles (21 clocks).

Huh, that's a typo.  Z80 CPU User's Manual UM008005-0205, page 102, M cycles is written as 2, but it's actually 3.

So the x86 is fairly indifferent, but this shouldn't be surprising for a quirky CISC like that; and Z80 is more comfortable with pointer arithmetic than (load-store at immediate address).

Tim
Seven Transistor Labs, LLC
Electronic design, from concept to prototype.
Bringing a project to life?  Send me a message!
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf