In a recent posting on high speed graphics Lance and others commented that SELECT is slower than other decision structures.
I have a program in PB/DLL 6.0 which creates pseudo UDT's (ie the program doesn't know the UDT structure in advance) and then sorts them with a binary sort, this is controlled with SELECT so as it is time critical I converted it to ON GOTO, to my surprise it ran 20% slower. To be precise in my test data I created 2.25 million pseudo UDT's with a structure of string * 18, long integer, string * 2. The SELECT method sorted then in 3 min 50 sec, the ON GOTO took 4 min 58 sec. I verified with the counters srtlpcnt& and efldcnt& that both verions went through the two decision structures the same number of times, 508 million times for the first and 271 million times for the second.
I then coded my own type of goto by building arrays of codeptr's to the labels and using a goto of the form :-
GOTO DWORD sel4(selection number)
this brought the time back to 3 min 52 sec. The claim that SELECT always using floating point seems strange as SELECT can also handle strings. From my time tests it would appear that the compiler is smart enough to construct something similar to the last method outlined. If this is the case then it would be even faster than IF - ELSEIF -ELSE constructs which do every test until they hit a match.
I have no idea why the ON GOTO was so slow, does anyone know what is the fastest decision method?
The code is below in SELECT form with the ON GOTO code remarked out.
The type of field to be sorted is stored in the integer array ka
Type 1 and 5 are strings, 2 and 6 are longs and 3 and 7 are double reals.
Type 1, 2 and 3 are sorted ascending, 5, 6 and 7 descending, the first field must be ascending.
------------------
[This message has been edited by John Petty (edited March 10, 2001).]
I have a program in PB/DLL 6.0 which creates pseudo UDT's (ie the program doesn't know the UDT structure in advance) and then sorts them with a binary sort, this is controlled with SELECT so as it is time critical I converted it to ON GOTO, to my surprise it ran 20% slower. To be precise in my test data I created 2.25 million pseudo UDT's with a structure of string * 18, long integer, string * 2. The SELECT method sorted then in 3 min 50 sec, the ON GOTO took 4 min 58 sec. I verified with the counters srtlpcnt& and efldcnt& that both verions went through the two decision structures the same number of times, 508 million times for the first and 271 million times for the second.
I then coded my own type of goto by building arrays of codeptr's to the labels and using a goto of the form :-
GOTO DWORD sel4(selection number)
this brought the time back to 3 min 52 sec. The claim that SELECT always using floating point seems strange as SELECT can also handle strings. From my time tests it would appear that the compiler is smart enough to construct something similar to the last method outlined. If this is the case then it would be even faster than IF - ELSEIF -ELSE constructs which do every test until they hit a match.
I have no idea why the ON GOTO was so slow, does anyone know what is the fastest decision method?
The code is below in SELECT form with the ON GOTO code remarked out.
The type of field to be sorted is stored in the integer array ka
Type 1 and 5 are strings, 2 and 6 are longs and 3 and 7 are double reals.
Type 1, 2 and 3 are sorted ascending, 5, 6 and 7 descending, the first field must be ascending.
Code:
swaplen& = keylen& \ 4 - 1 offset&= (xx& + 1) \ 2 DO WHILE offset& > 0 lmt& = xx& - offset& DO swtch& = 0 FOR yy& = 0 TO lmt& eql& = -1 swp& = 0 srtlpcnt& = srtlpcnt& + 1 ibp1 =VARPTR(ind1(0))+ yy& * keylen& wbp1 = VARPTR(ind1(0)) +(yy& + offset&) * keylen& SELECT CASE ka(0,0,kma) 'ON ka(0,0,kma)GOTO sel05_1, sel05_2, sel05_3 'GOTO ESel05 CASE 1 'sel05_1: dwp1 = ibp1 dwp2 = wbp1 FOR u& = 0 TO sslen(0) - 1 IF @dwp1[u&] > @dwp2[u&] THEN swp& = -1 swtch& = yy& EXIT FOR ELSEIF @dwp1[u&] < @dwp2[u&] THEN eql& = 0 EXIT FOR END IF NEXT 'GOTO ESel05 CASE 2 'sel05_2: wolp = ibp1 wlp1 = wbp1 IF @wolp > @wlp1 THEN swp& = -1 swtch& = yy& ELSEIF @wolp < @wlp1 THEN eql& = 0 END IF 'GOTO ESel05 CASE 3 'sel05_3: wodp = ibp1 wdp1 = wbp1 IF @wodp > @wdp1 THEN swp& = -1 swtch& = yy& ELSEIF @wodp < @wdp1 THEN eql& = 0 END IF END SELECT 'ESel05: zz& = 1 DO WHILE eql& AND zz& <= numkeys& efldcnt& = efldcnt& + 1 SELECT CASE ka(zz&,0,kma) 'ON ka(zz&,0,kma) GOTO sel04_1, sel04_2, Sel04_3, ESel04, sel04_5, sel04_6, sel04_7 'GOTO ESel04 CASE 1 'sel04_1: dwp1 = ibp1 + koff1(zz&) dwp2 = wbp1 + koff1(zz&) FOR u& = 0 TO sslen(zz&) - 1 IF @dwp1[u&] > @dwp2[u&] THEN swp& = -1 swtch& = yy& EXIT FOR ELSEIF @dwp1[u&] < @dwp2[u&] THEN eql& = 0 EXIT FOR END IF NEXT 'GOTO ESel04 CASE 2 'sel04_2: wolp = ibp1 + koff1(zz&) wlp1 = wbp1 + koff1(zz&) IF @wolp > @wlp1 THEN swp& = -1 swtch& = yy& ELSEIF @wolp < @wlp1 THEN eql& = 0 END IF 'GOTO ESel04 CASE 3 'sel04_3: wodp = ibp1 + koff1(zz&) wdp1 = wbp1 + koff1(zz&) IF @wodp > @wdp1 THEN swp& = -1 swtch& = yy& ELSEIF @wodp < @wdp1 THEN eql& = 0 END IF 'GOTO ESel04 CASE 5 'sel04_5: dwp1 = ibp1 + koff1(zz&) dwp2 = wbp1 + koff1(zz&) FOR u& = 0 TO sslen(zz&) - 1 IF @dwp1[u&] < @dwp2[u&] THEN swp& = -1 swtch& = yy& EXIT FOR ELSEIF @dwp1[u&] > @dwp2[u&] THEN eql& = 0 EXIT FOR END IF NEXT 'GOTO ESel04 CASE 6 'sel04_6: wolp = ibp1 + koff1(zz&) wlp1 = wbp1 + koff1(zz&) IF @wolp < @wlp1 THEN swp& = -1 swtch& = yy& ELSEIF @wolp > @wlp1 THEN eql& = 0 END IF 'GOTO ESel04 CASE 7 'sel04_7: wodp = ibp1 + koff1(zz&) wdp1 = wbp1 + koff1(zz&) IF @wodp < @wdp1 THEN swp& = -1 swtch& = yy& ELSEIF @wodp > @wdp1 THEN eql& = 0 END IF END SELECT 'ESel04: zz& = zz& +1 LOOP IF swp& THEN dwp1 = ibp1 dwp2 = wbp1 FOR u& = 0 TO swaplen& @dwps[u&] = @dwp1[u&] @dwp1[u&] = @dwp2[u&] @dwp2[u&] = @dwps[u&] NEXT END IF NEXT lmt& = swtch& LOOP WHILE swtch& offset& = offset& \ 2 LOOP
[This message has been edited by John Petty (edited March 10, 2001).]
Comment