Dhrystone compiled on BBQL with Digital C SE

Anything QL Software or Programming Related.
User avatar
tofro
Font of All Knowledge
Posts: 2685
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: Dhrystone compiled on BBQL with Digital C SE

Post by tofro »

bwinkel67 wrote: So the source has local variables set up with the register directive (REG), which suggests that some of the older compilers can assign a register to a specific variable. I imagine that would speed things up. Unfortunately Digital C SE doesn't give that feature. I'm guessing Metacomco C does? That's got to be how it is still faster.
Mecacomco C (and C68, BTW) are full-blown C compilers compared to Digital C, which is Small C and has to live with its limitations. Both support the register storage class. As it stands, register is only a recommendation from the developer to the compiler that a variable is going to see heavy usage and it would make sense to put it in a register. In case the compiler runs out of unassigned registers, or sees, for example, that the variable's address is taken anywhere, it will simply ignore this recommendation (but might also put other variables into registers where you didn't explicitly say so).


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
User avatar
XorA
Site Admin
Posts: 1358
Joined: Thu Jun 02, 2011 11:31 am
Location: Shotts, North Lanarkshire, Scotland, UK

Re: Dhrystone compiled on BBQL with Digital C SE

Post by XorA »

which is 16 bits on the QL
That is a bloomin odd choice for any C implementation on QL, as the natural size is 32bits or 8bjts depending how you look at the CPU.

Graeme


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: Dhrystone compiled on BBQL with Digital C SE

Post by bwinkel67 »

XorA wrote:
which is 16 bits on the QL
That is a bloomin odd choice for any C implementation on QL, as the natural size is 32bits or 8bjts depending how you look at the CPU.

Graeme
Digital C SE doesn't have a short specification, only int and long. With other compilers (I don't know the specifics ot Metacomco C or C68 but I'm going to guess they do) you have short, int, and long. In that case, on a 32 bit system int and long would be 32 bits and short would be 16 bits. On a 64 bit system, short would be 16 bits, int would be 32 bits, and long would be 64 bits. So in Digital C SE's instance, the 16 bits makes sense.


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: Dhrystone compiled on BBQL with Digital C SE

Post by bwinkel67 »

tofro wrote:Mecacomco C (and C68, BTW) are full-blown C compilers compared to Digital C, which is Small C and has to live with its limitations. Both support the register storage class. As it stands, register is only a recommendation from the developer to the compiler that a variable is going to see heavy usage and it would make sense to put it in a register. In case the compiler runs out of unassigned registers, or sees, for example, that the variable's address is taken anywhere, it will simply ignore this recommendation (but might also put other variables into registers where you didn't explicitly say so).
Yeah, that's what I'm running into with regard to speed in Digital C SE...not being able to specify a variable as a register, which is costing me speed. I'm trying to figure out ways around that since I can't explicitly specify register. I'm sure I'll find other creative ways to optimize...that's part of the fun challenge.

Digital C SE is an augmented Small C. It adds its own implementation of floating point. I think it also added the long integer type, because when reading the manual it states that SE has introduced long. This leads me to believe the non-SE version didn't have long so it was likely the one more closely aligned with Small C.


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: Dhrystone compiled on BBQL with Digital C SE

Post by bwinkel67 »

Here are some updated results on Dhrystone (includes both version 1.1 and 1.2 of Dhrystone):
  • Digital C SE with a few optimizations on v1.1: 164
  • Metacomco C on v1.1 (Franz Krojer , 1988): 196
  • C68 on v1.2 (Franz Krojer, 1994): 282
I think that 3rd one was C68, only because that same website had a ton of C68 stuff on it. Note that there are only small changes between v1.1 and v1.2 of Dhrystone. The one that stood out was defining SINT and LINT for specific short int and long int variables.

I got these values on Q-Emulator running in real-time on my 68K classic Mac Emulator (Basilisk II). I don't usually use Q-Emulator so I don't have a licensed Windows version but the old 68K classic version (3.0.4) seems to be fully functional. I have to say, Q-Emulator gave me the same result (196 Dhrystones) that my QL gave me. I was going to re-run all these on the QL but my vDrive stopped functioning today so it's not as easy to get it transferred over.

Note that the C68 version runs 500,000 iterations so it takes close to half an hour to get a result.

So next is to see if I can improve on the Digital C SE version. I can't force variables to registers, but I can unfold loops, and force caching, to improve some things. Would like it to get at least as good as the Metacomco version.

The only other results I still need is GCC's cross-compiled version for the QL. I read somewhere that it is even faster than C68. Still, 282 Dhrystones is pretty impressive.


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: Dhrystone compiled on BBQL with Digital C SE

Post by bwinkel67 »

Ok, finally ran my Digital C SE version on my QL (read the "Serial connection between QL and PC" to see how I had to get the executable to my QL the old-school way. It actually ran faster at 176 Dhrystones. Weird because the Metacomco version ran at 196, same as on Q-emulator. The one small cavat, small dots are appearing in the middle of the screen, so I seem to be writing into screen memory somewhere which I'll have to debug. Q-emulator (and QLAY), both with 128K memory setting and running JSU ROM, didn't show that.

So with legitimate small optimizations, I get 176 Dhrystones to 196 Dhrystones. Still far off form the C68 version though :-(


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: Dhrystone compiled on BBQL with Digital C SE

Post by bwinkel67 »

Looking further at my Digital C SE implementation of Dhrystone, since it seems to be writing to screen memory when running on my actual BBQL (i.e. I get little dots in the middle of my screen), I went over the code to figure out why. So in both of Franz Krojer's implementations of Dhrystone, version 1.1 (compiled with Metacomco) and version 1.2 (compiled with C68), it has the following code snippet (I marked up the two lines of interest with /* <-- ??????? */):

Code: Select all

struct Record { 
  struct Record* PtrComp; 
  Enumeration Discr; 
  Enumeration EnumComp; 
  OneToFifty IntComp; 
  String30 StringComp; 
}; 
 
typedef struct Record RecordType; 
typedef RecordType* RecordPtr; 


...


void Proc1(PtrParIn)
REG RecordPtr PtrParIn; 
{ 
#define NextRecord  (*(PtrParIn->PtrComp)) 
 
  structassign(NextRecord, *PtrGlb); 
  PtrParIn->IntComp = 5; 
  NextRecord.IntComp = PtrParIn->IntComp; 
  NextRecord.PtrComp = PtrParIn->PtrComp; 
  Proc3(NextRecord.PtrComp);       /* <-- ??????? */
  if (NextRecord.Discr == Ident1) { 
    NextRecord.IntComp = 6; 
    Proc6(PtrParIn->EnumComp, &NextRecord.EnumComp); 
    NextRecord.PtrComp = PtrGlb->PtrComp; 
    Proc7(NextRecord.IntComp, 10, &NextRecord.IntComp); 
  } else 
    structassign(*PtrParIn, NextRecord); 
 
#undef  NextRecord 
} 


...


void Proc3(PtrParOut)
RecordPtr* PtrParOut;                    /* <- this is equivalent to having 2 asterisks, i.e.: struct Record** PtrParOut; */
{ 
  if (PtrGlb != NULL) 
    *PtrParOut = PtrGlb->PtrComp;        /* <-- ??????? */
  else 
    IntGlob = 100; 
  Proc7(10, IntGlob, &PtrGlb->IntComp); 
} 
Looking at this code, I was confused by the lines marked with /* <-- ??????? */ because in Proc3() you have a pointer to RecordPtr (i.e. RecordPtr*) and in Proc1() you are only sending a RecordPtr (i.e. the types misalign). That's critical because in Proc3() you then re-reference that pointer to set it -- but you never de-referenced it when calling the function, so it never gets updated in Proc1() and any subsequent code that uses that variable (it's tied to a global) may be looking at a NULL pointer, which could cause things to speed up a bit since you may now no longer follow a linked-list of record pointers (I need to figure out if that's the case).

Looking here at some original source with comments:

https://github.com/Keith-S-Thompson/dhr ... ces/dhry-c

It verifies my hunch as in Proc1() they add a de-reference operator to the Proc3() call:

Code: Select all

Proc_1 (Ptr_Val_Par)
REG Rec_Pointer Ptr_Val_Par;
{
  REG Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp;  

  structassign (*Ptr_Val_Par->Ptr_Comp, *Ptr_Glob); 
  Ptr_Val_Par->variant.var_1.Int_Comp = 5;
  Next_Record->variant.var_1.Int_Comp  = Ptr_Val_Par->variant.var_1.Int_Comp;
  Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp;
  Proc_3 (&Next_Record->Ptr_Comp);       /* <-- ??????? */
  if (Next_Record->Discr == Ident_1) {
    Next_Record->variant.var_1.Int_Comp = 6;
    Proc_6 (Ptr_Val_Par->variant.var_1.Enum_Comp, 
           &Next_Record->variant.var_1.Enum_Comp);
    Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp;
    Proc_7 (Next_Record->variant.var_1.Int_Comp, 10, 
           &Next_Record->variant.var_1.Int_Comp);
  }
  else
    structassign (*Ptr_Val_Par, *Ptr_Val_Par->Ptr_Comp);
}
That code changed it a bit to get rid of that ugly #define that, when expanded, causes a messy looking procedure call in the first code example, i.e.

Code: Select all

Proc3((*PtrParIn->PtrComp).PtrComp);
...which is equivalent in C to:

Code: Select all

Proc3(PtrParIn->PtrComp->PtrComp);
...yes, not very pretty code.

Just curious if I'm mis-reading the QL Metacomco C and C68 code here? Anyone with a good C background that has used either of these QL C compilers have an idea if I'm right or wrong here?
Last edited by bwinkel67 on Mon Aug 08, 2022 7:10 am, edited 1 time in total.


User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: Dhrystone compiled on BBQL with Digital C SE

Post by bwinkel67 »

I must just be misunderstanding how C works here. I found the original version 1.1 of Dhrystone and it's the same as Franz Krojers with regard to Proc1():

https://github.com/Keith-S-Thompson/dhr ... hrystone.c

So sending a pointer to a pointer...i.e.:

Code: Select all

Proc3(PtrParIn->PtrComp->PtrComp);
...is the same as doing this????

Code: Select all

RecordPtr NextRec = PtrParIn->PtrComp;

...

Proc3(&NextRec->PtrComp);
I'm having difficulty wrapping my head around this...

In any case, Digital C SE forced me to do it the way of the 2nd example (i.e. do an assignment to NextRec), and so I think I found my error because I excluded the & in my call to Proc3() since I was trying to match the 1st example.


User avatar
tofro
Font of All Knowledge
Posts: 2685
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: Dhrystone compiled on BBQL with Digital C SE

Post by tofro »

Imagine the following linked list:

(The numbers are the addresses where the structs live)

Code: Select all

          a)                  b)             c)
          100                 200             300
PtrParIn->PtrComp------------>PtrComp-------->PtrComp
          Discr               Discr           Discr
          EnumComp	         EnumComp        EnumComp
                          ....                        ........
      
Then PtrParInt->PtrComp->PtrComp is the value of PtrComp in instance b) of the record that points to PtrComp in instance c), so "300"

NextRec in your second example is the value of PtrComp in instance a). (200)
The address of NextRec->ptrComp is then simply the value of NextRec (or, simply a pointer to instance b) ) which is something entirely different than in your first example. (again 200)

(Not quite knowing what you want makes it a bit difficult to tell you what to write)


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
User avatar
bwinkel67
QL Wafer Drive
Posts: 1187
Joined: Thu Oct 03, 2019 2:09 am

Re: Dhrystone compiled on BBQL with Digital C SE

Post by bwinkel67 »

tofro wrote:Imagine the following linked list:
Oh, that table is a good way to work through the problem...thank you. Let me give it some thought to see if it's doing what it is supposed to.


Post Reply