Announcement

Collapse
No announcement yet.

Image statistics with assembler?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Image statistics with assembler?

    Hello,

    I'd like to do some rudimentary image processing fast, and was wondering
    if an amature like me should even attempt the task with inline assembler.
    The source image is "grayscale" with some width and height. Each
    pixel is an intensity value represented by 8, 16, or 32 bits. The 32 bit
    flavor could be integer or floating point. I know how to get a pointer to
    the image buffer or even make a copy. The following is what I'd like to know
    about the image (really fast):

    1) The average intensity value - i.e., sum everything up and divide by the
    total number of pixels.
    2) The intensity variance - i.e., sum up the square of the difference between
    every pixel and the average intensity, and then divide the result by the total
    number of pixels.
    3) The centroid - i.e., multiply every pixel value by its x or y position, and
    keep a running total in the x and y direction. When done, divide the x sum and y sum
    by the average above.

    Am I biting off more that I can chew?

    -CMR

    ------------------

  • #2
    Am I biting off more that I can chew?
    Depends on your level of assembly language experience/skill...

    The question you have to ask is, will time spent on floating point math, etc., be worth the possibly minimal speed increase?

    ------------------
    Adam Drake
    PowerBASIC

    Comment


    • #3
      CMR,
      <<Am I biting off more that I can chew?>>

      Maybe, but you'll very soon grow the teeth you need if you give it a go.
      All of the things you describe are quite simple to do in ASM.

      Go for it.

      Paul.


      ------------------

      Comment


      • #4
        For the tasks you describe, I think I'd bet cash money that well-written BASIC will outperform self-described amateur assembly-language code.

        I mean, the PB compilers handle add, subtract, multiply and divide pretty effectively.


        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          CMR,
          go for it. Michael will even pay you to do it!

          Paul.


          ------------------

          Comment


          • #6
            Alright, I'll bite, but I must admit I could use a hand. Perhaps a
            kind soul could provide ASM code for the following to get me started:

            Let's say I have an array, values(0 to 999, 0 to 999), and all the elements
            are set to 1.

            Using ASM, I want to add all the elements up and divide by 1000000. The
            result should end up in a long variable called sum. Any takers?

            -CMR


            ------------------

            Comment


            • #7
              CM,

              While I would never discourage you from extending your knowhow with
              the very good inline assembler in PB, I would still tend to prototype
              what you are after first with high level PB paying particular attention
              to ensuring that you write efficient minimal code without redundancies
              in it first.

              See how it shapes up first and if its not fast enough, then you can
              think about trying to tweak it in assembler. Something I regularly see
              is someone using a piece of very fast assembler code that may execute
              in a couple of hundred milliseconds then turn it into a 3 second
              execution time by adding the wrong high level code to it.

              What I am suggesting here is gradualism so you get the high level
              code efficient enough so that if you really do need to write the
              intensive code in assembler, it won't be wasted by the rest of the
              code.

              Regards,

              hutch at movsd dot com

              ------------------
              hutch at movsd dot com
              The MASM Forum

              www.masm32.com

              Comment


              • #8
                CMR,
                no doubt MCM will claim you've had non-amateur help and his cash offer is therefore void, but I'm an amateur, honest..
                Code:
                DEFLNG A-Z,a-z      ' we're using LONGS as default
                FUNCTION PBMAIN () AS LONG
                'first, set things up as you requested
                DIM a(999,999)
                  
                FOR row=0 TO 999
                    FOR col=0 TO 999
                        a(col,row)=RND(1,200)
                    NEXT
                NEXT
                   
                'next, do it in BASIC so you know how things need to be done
                sum=0
                FOR row=0 TO 999
                    FOR col=0 TO 999
                        sum=sum+a(col,row)
                    NEXT
                NEXT
                ans=sum\1000000
                PRINT "BASIC ans=";ans
                  
                WAITKEY$
                     
                'now,try it in ASM, not optimal, but easier to follow
                arrayptr=VARPTR(a(0,0))      'get the address of the first element of the array
                   
                !pushad                 ;save all registers, don't need to but it's safer.
                   
                !mov sum,0              ;sum=0
                !mov row,0              ;start of "FOR col=0 TO 999"
                RowLoop:
                !mov col,0              ;start of "FOR row=0 TO 999"
                ColLoop:
                   
                'sum=sum+a(col,row)
                !mov ebx,row            ;get the row
                !imul ebx,1000          ;1000 elements per row so multiply by 1000
                !add ebx,col            ;add the col
                !mov edx,arrayptr       ;get the address of the start of the array
                !mov eax,[edx+ebx*4]    ;get the array element, EBX*4 as each element is 4 bytes
                !add sum,eax            ;add it to the sum so far
                     
                !inc col                ;NEXT col
                !cmp col,999            ;
                !jle ColLoop            ;jump if Less than or Equal to 999
                   
                !inc row                ;NEXT row
                !cmp row,999
                !jle RowLoop            ;jump if Less than or Equal to 999
                    
                !popad                  ;restore all registers after ASM is done
                   
                ans=sum\1000000
                PRINT "First ASM ans=";ans
                  
                WAITKEY$
                  
                'now look for obvious optimisations
                arrayptr=VARPTR(a(0,0))      'get the address of the first element of the array
                   
                !pushad                 ;save all registers, don't need to but it's safer.
                   
                !mov sum,0              ;sum=0
                !mov row,0              ;start of "FOR col=0 TO 999"
                RowLoop2:
                !mov col,0              ;start of "FOR row=0 TO 999"
                   
                'Why calculate the row offset and array start every time when it never changes within the inner loop?
                'do it outside the loop instead
                !mov edx,row            ;get the row
                !imul edx,4000          ;4000 bytes per row so multiply by 4000
                !add edx,arrayptr       ;add the offset to the start of the array
                   
                ColLoop2:
                'sum=sum+a(col,row)
                !mov ebx,col            ;get the col
                !mov eax,[edx+ebx*4]    ;get the array element, EBX*4 as each element is 4 bytes
                !add sum,eax            ;add it to the sum so far
                 
                !inc col                ;NEXT col
                !cmp col,999            ;
                !jle ColLoop2           ;jump if Less than or Equal to 999
                  
                !inc row                ;NEXT row
                !cmp row,999
                !jle RowLoop2           ;jump if Less than or Equal to 999
                  
                !popad                  ;restore all registers after ASM is done
                  
                 
                ans=sum\1000000
                PRINT "Second ASM ans=";ans
                 
                WAITKEY$
                  
                 
                'next step is to do it better in ASM ..   but that's not for absolute beginners
                'first, note that there are 6 available registers so why not use them instead of RAM?
                !pushad                 ;save all registers
                  
                !mov eax,0              ;sum=0, now kept in a register
                !mov edi,0              ;start of "FOR col=0 TO 999"
                RowLoop3:
                !mov edx,0              ;start of "FOR row=0 TO 999"
                  
                'Why calculate the row offset and array start every time when it never changes within the inner loop?
                'do it outside the loop instead
                !mov ebx,edi
                !imul ebx,4000          ;4000 bytes per row so multiply by 4000
                !add ebx,arrayptr       ;add the offset to the start of the array
                 
                ColLoop3:
                'sum=sum+a(col,row)
                !add eax,[ebx+edx*4]    ;get the array element, EDI*4 as each element is 4 bytes
                 
                !inc edx                ;NEXT col
                !cmp edx,999            ;
                !jle ColLoop3           ;jump if Less than or Equal to 999
                 
                !inc edi                ;NEXT row
                !cmp edi,999
                !jle RowLoop3           ;jump if Less than or Equal to 999
                 
                !mov edx,0
                !mov ecx,1000000
                !mov sum,eax
                 
                !div ecx
                !mov ans,eax
                !popad                  ;restore all registers after ASM is done
                 
                PRINT "faster ASM=";ans
                 
                WAITKEY$
                 
                 
                'Now look for finer optimisations..
                !pushad                 ;save all registers
                 
                !mov eax,0              ;sum=0, now kept in a register
                !mov edi,999*4000       ;faster to count down to 0, we can avoid a multiply by including the *4000 here
                RowLoop4:
                !mov edx,999            ;faster to count down to 0,
                 
                'Why calculate the row offset and array start every time when it never changes within the inner loop?
                'do it outside the loop instead
                !mov ebx,edi
                !add ebx,arrayptr       ;add the offset to the start of the array
                 
                ColLoop4:
                'sum=sum+a(col,row)
                !add eax,[ebx+edx*4]    ;get the array element, EDI*4 as each element is 4 bytes
                 
                !dec edx                ;NEXT col
                !jns  ColLoop4          ;jump if positive (NS=not sign, i.e. sign bit not set)
                 
                !sub edi,4000           ;NEXT row, 400 bytes per row
                !jns  RowLoop4          ;jump if positive (NS=not sign, i.e. sign bit not set)
                 
                !mov edx,0              ;clear the high word ready for a 64 bit divide
                !mov ecx,1000000        ;the number to divide by
                 
                !div ecx                ;do the division by 1000000
                !mov ans,eax            ;copy result to "ans"
                 
                !popad                  ;restore all registers after ASM is done
                 
                PRINT "faster still ASM=";ans
                 
                WAITKEY$
                 
                
                END FUNCTION
                I hope that helps. There is more that can be done to speed it up, in particular, the array is a single block or RAM so there's no need for 2 loops in this case, one would work and be a little quicker.

                Paul.


                ------------------

                Comment


                • #9
                  Paul,

                  Thanks for the detailed example - it's just what I was looking for.

                  -CMR

                  ------------------

                  Comment


                  • #10
                    >no doubt MCM will claim you've had non-amateur help ..

                    He does.
                    Michael Mattias
                    Tal Systems (retired)
                    Port Washington WI USA
                    [email protected]
                    http://www.talsystems.com

                    Comment


                    • #11
                      I knew I should have contacted CMR by e-mail then we could've split the profits, 50c each.

                      Paul.


                      ------------------

                      Comment


                      • #12
                        Personnellement j'utiliserai un DIB avec des pointeurs.
                        C'est très très rapide.


                        ------------------
                        Patrice Terrier
                        mailto[email protected][email protected]</A>
                        www.zapsolution.com
                        Addons: WinLIFT (Skin Engine), GDImage (Graphic control), Artwork (logo creation), GDI+ Helper (GDIPLUS)
                        Patrice Terrier
                        www.zapsolution.com
                        www.objreader.com
                        Addons: GDImage.DLL 32/64-bit (Graphic library), WinLIFT.DLL 32/64-bit (Skin Engine).

                        Comment


                        • #13
                          DIB avec des pointeurs BASIC, c'est très très rapide.
                          DIB avec des pointeurs ASM, c'est très très très rapide.

                          ------------------

                          Comment


                          • #14
                            Although I haven't incorporated an ASM test segment yet, this is what I've
                            come up with in terms of comparing speeds using a pointer method
                            to one using indexes. On my 2GHz P4-M I'm getting ~296 ms for the index
                            method and ~229 ms for the pointer method. These numbers are based on
                            running the routine 100 times (variable n below). I'm using a 1392x1040
                            array populated with random 12 bit numbers to mimic the size and type of
                            image produced by a typical scientific CCD. Are there ways to tighten the
                            pointer method? Once done, will I gain much by recasting this method in
                            ASM? Assuming a 2Ghz or so machine, is sub 100 or even 10 ms possible?
                            Just curious. Thanks for all your help so far.

                            -CMR



                            Code:
                            #PBFORMS CREATED V1.51
                            '------------------------------------------------------------------------------
                            ' The first line in this file is a PB/Forms metastatement.
                            ' It should ALWAYS be the first line of the file. Other
                            ' PB/Forms metastatements are placed at the beginning and
                            ' end of "Named Blocks" of code that should be edited
                            ' with PBForms only. Do not manually edit or delete these
                            ' metastatements or PB/Forms will not be able to reread
                            ' the file correctly.  See the PB/Forms documentation for
                            ' more information.
                            ' Named blocks begin like this:    #PBFORMS BEGIN ...
                            ' Named blocks end like this:      #PBFORMS END ...
                            ' Other PB/Forms metastatements such as:
                            '     #PBFORMS DECLARATIONS
                            ' are used by PB/Forms to insert additional code.
                            ' Feel free to make changes anywhere else in the file.
                            '------------------------------------------------------------------------------
                            
                            #COMPILE EXE
                            '#DIM ALL
                            
                            '------------------------------------------------------------------------------
                            '   ** Includes **
                            '------------------------------------------------------------------------------
                            #PBFORMS BEGIN INCLUDES 
                            #IF NOT %DEF(%WINAPI)
                                #INCLUDE "WIN32API.INC"
                            #ENDIF
                            #PBFORMS END INCLUDES
                            '------------------------------------------------------------------------------
                            
                            '------------------------------------------------------------------------------
                            '   ** Constants **
                            '------------------------------------------------------------------------------
                            #PBFORMS BEGIN CONSTANTS 
                            %IDD_DIALOG1 =  101
                            %IDC_METHOD1 = 1002
                            %IDC_METHOD2 = 1003
                            %IDC_GO1     = 1001
                            %IDC_GO2     = 1004
                            %IDC_YPOZ1   = 1007
                            %IDC_XPOZ1   = 1005
                            %IDC_XPOZ2   = 1006
                            %IDC_VAR1    = 1009
                            %IDC_YPOZ2   = 1008
                            %IDC_VAR2    = 1010
                            #PBFORMS END CONSTANTS
                            '------------------------------------------------------------------------------
                            
                            '------------------------------------------------------------------------------
                            '   ** Declarations **
                            '------------------------------------------------------------------------------
                            DECLARE CALLBACK FUNCTION ShowDIALOG1Proc()
                            DECLARE FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                            #PBFORMS DECLARATIONS
                            '------------------------------------------------------------------------------
                            
                            '------------------------------------------------------------------------------
                            '   ** Main Application Entry Point **
                            '------------------------------------------------------------------------------
                            FUNCTION PBMAIN()
                                ShowDIALOG1 %HWND_DESKTOP
                            END FUNCTION
                            '------------------------------------------------------------------------------
                            
                            '------------------------------------------------------------------------------
                            '   ** CallBacks **
                            '------------------------------------------------------------------------------
                            CALLBACK FUNCTION ShowDIALOG1Proc()
                            
                                SELECT CASE AS LONG CBMSG
                                    CASE %WM_INITDIALOG
                                        ' Initialization handler
                                        DIM values(0 TO 1391, 0 TO 1039) AS STATIC DWORD
                                        DIM pValues AS LONG POINTER
                                        DIM sum AS DWORD
                                        DIM var AS DWORD
                                        DIM xsum AS QUAD
                                        DIM ysum AS QUAD
                                        DIM n AS STATIC LONG
                            
                                        RANDOMIZE TIMER
                            
                                        FOR i&=0 TO 1391
                                            FOR j&=0 TO 1039
                                                values(i&,j&)=RND(0,4095)
                                            NEXT
                                        NEXT
                            
                                        n=100
                            
                                    CASE %WM_NCACTIVATE
                                        STATIC hWndSaveFocus AS DWORD
                                        IF ISFALSE CBWPARAM THEN
                                            ' Save control focus
                                            hWndSaveFocus = GetFocus()
                                        ELSEIF hWndSaveFocus THEN
                                            ' Restore control focus
                                            SetFocus(hWndSaveFocus)
                                            hWndSaveFocus = 0
                                        END IF
                            
                                    CASE %WM_COMMAND
                                        ' Process control notifications
                                        SELECT CASE AS LONG CBCTL
                                            ' /* Inserted by PB/Forms 04-21-2006 19:03:08
                                            CASE %IDC_VAR1
                            
                                            CASE %IDC_VAR2
                                            ' */
                            
                                            ' /* Inserted by PB/Forms 04-21-2006 17:14:12
                                            CASE %IDC_GO1
                                                IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                                    'MSGBOX "%IDC_GO1=" + FORMAT$(%IDC_GO1), %MB_TASKMODAL
                                                    zero!=TimeGetTime
                                                    FOR c&=1 TO n
                                                        sum=0
                                                        var=0
                                                        xsum=0
                                                        ysum=0
                                                        FOR i&=0 TO 1391
                                                            FOR j&=0 TO 1039
                                                                sum=sum+values(i&,j&)
                                                                xsum=xsum+i&*values(i&,j&)
                                                                ysum=ysum+j&*values(i&,j&)
                                                            NEXT
                                                        NEXT
                                                        xsum=xsum/sum
                                                        ysum=ysum/sum
                                                        sum=sum/1447679
                                                        FOR i&=0 TO 1391
                                                            FOR j&=0 TO 1039
                                                                var=var+ABS(sum-values(i&,j&))
                                                            NEXT
                                                        NEXT
                                                        var=var/1447679
                                                    NEXT
                                                    duration!=TimeGetTime-zero!
                                                    CONTROL SET TEXT CBHNDL, %IDC_METHOD1, FORMAT$(duration!/n)+"ms"
                                                    CONTROL SET TEXT CBHNDL, %IDC_XPOZ1, FORMAT$(xsum)
                                                    CONTROL SET TEXT CBHNDL, %IDC_YPOZ1, FORMAT$(ysum)
                                                    CONTROL SET TEXT CBHNDL, %IDC_VAR1, FORMAT$(var)
                            
                                                END IF
                            
                                            CASE %IDC_GO2
                                                IF CBCTLMSG = %BN_CLICKED OR CBCTLMSG = 1 THEN
                                                    'MSGBOX "%IDC_GO2=" + FORMAT$(%IDC_GO2), %MB_TASKMODAL
                                                    pValues=VARPTR(values(0,0))
                                                    zero!=TimeGetTime
                                                    FOR c&=1 TO n
                                                        sum=0
                                                        var=0
                                                        xsum=0
                                                        ysum=0
                                                        FOR i&=0 TO 1447679
                                                            [email protected]
                                                            xsum=xsum+(i& MOD 1392)*@pValues
                                                            ysum=ysum+(i&\1392)*@pValues
                                                            INCR pValues
                                                        NEXT
                                                        xsum=xsum/sum
                                                        ysum=ysum/sum
                                                        sum=sum/1447679
                                                        FOR i&=0 TO 1447679
                                                            DECR pValues
                                                            var=var+ABS([email protected])
                                                        NEXT
                                                        var=var/1447679
                                                    NEXT
                                                    duration!=TimeGetTime-zero!
                                                    CONTROL SET TEXT CBHNDL, %IDC_METHOD2, FORMAT$(duration!/n)+"ms"
                                                    CONTROL SET TEXT CBHNDL, %IDC_XPOZ2, FORMAT$(xsum)
                                                    CONTROL SET TEXT CBHNDL, %IDC_YPOZ2, FORMAT$(ysum)
                                                    CONTROL SET TEXT CBHNDL, %IDC_VAR2, FORMAT$(var)
                            
                                                END IF
                                            ' */
                            
                                            CASE %IDC_METHOD1
                            
                                            CASE %IDC_METHOD2
                            
                                        END SELECT
                                END SELECT
                            END FUNCTION
                            '------------------------------------------------------------------------------
                            
                            '------------------------------------------------------------------------------
                            '   ** Dialogs **
                            '------------------------------------------------------------------------------
                            FUNCTION ShowDIALOG1(BYVAL hParent AS DWORD) AS LONG
                                LOCAL lRslt AS LONG
                            
                            #PBFORMS BEGIN DIALOG %IDD_DIALOG1->->
                                LOCAL hDlg  AS DWORD
                            
                                DIALOG NEW hParent, "speedtest", 121, 129, 313, 77, %WS_POPUP OR _
                                    %WS_BORDER OR %WS_DLGFRAME OR %WS_SYSMENU OR %WS_CLIPSIBLINGS OR _
                                    %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR _
                                    %DS_SETFONT, %WS_EX_WINDOWEDGE OR %WS_EX_CONTROLPARENT OR _
                                    %WS_EX_LEFT OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
                                CONTROL ADD BUTTON,  hDlg, %IDC_GO1, "Go1", 4, 15, 90, 20
                                CONTROL ADD TEXTBOX, hDlg, %IDC_METHOD1, "method1", 100, 15, 40, 20
                                CONTROL ADD TEXTBOX, hDlg, %IDC_METHOD2, "method2", 100, 40, 40, 20
                                CONTROL ADD BUTTON,  hDlg, %IDC_GO2, "Go2", 5, 40, 90, 20
                                CONTROL ADD TEXTBOX, hDlg, %IDC_XPOZ1, "xpoz1", 146, 15, 50, 20
                                CONTROL ADD TEXTBOX, hDlg, %IDC_XPOZ2, "xpoz2", 146, 40, 50, 20
                                CONTROL ADD TEXTBOX, hDlg, %IDC_YPOZ1, "ypoz1", 201, 15, 50, 20
                                CONTROL ADD TEXTBOX, hDlg, %IDC_YPOZ2, "ypoz2", 201, 40, 50, 20
                                CONTROL ADD TEXTBOX, hDlg, %IDC_VAR1, "var1", 257, 15, 50, 20
                                CONTROL ADD TEXTBOX, hDlg, %IDC_VAR2, "var2", 257, 40, 50, 20
                            #PBFORMS END DIALOG
                            
                                DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc TO lRslt
                            
                            #PBFORMS BEGIN CLEANUP %IDD_DIALOG1
                            #PBFORMS END CLEANUP
                            
                                FUNCTION = lRslt
                            END FUNCTION
                            '------------------------------------------------------------------------------
                            ------------------

                            Comment


                            • #15
                              CMR,
                              sub 100ms is easily possible.
                              sub 10ms may be possible, I'm not sure without trying it but it's not an outrageous time to wish for.

                              Paul.


                              ------------------

                              Comment


                              • #16
                                Paul,

                                I'm pretty sure I can figure out the sum and centroid part, but how
                                would one do ABS(value1-value2) is ASM?

                                -CMR



                                ------------------

                                Comment


                                • #17
                                  CMR,
                                  to get ABS(val1-val2) use this:
                                  Code:
                                  !mov eax,val1   'get val1 into a register
                                  !sub eax,val2   'subtract val2
                                  !jns skip       'if sign not set (i.e.result is positive) skip the next instruction
                                  !neg eax        'negate the answer to make the -ve number +ve
                                  skip:
                                  !mov ans,eax    'write the result to where we need it.
                                  Also, in your pointer code above you have a single loop and you extract the X and Y values using (i& MOD 1392) and (i&\1392). This is a slow way to do it.
                                  MOD and \ are slow operations. It would be quicker if you left it as 2 loops as the extra loop overhead will be small compared to the time to calculate MOD and \.

                                  Paul.


                                  ------------------

                                  Comment


                                  • #18
                                    CMR,
                                    <<Are there ways to tighten the pointer method?>>

                                    Yes, but you can do better with the array method too.
                                    Try changing your FOR..NEXT loops in the array method to this:
                                    Code:
                                    FOR j&=0 TO 1039
                                       FOR i&=0 TO 1391
                                         k&=values(i&,j&)
                                         sum=sum+k&
                                         xsum=xsum+i&*k&
                                         ysum=ysum+j&*k&
                                       NEXT
                                    NEXT
                                    The 2 improvements are:
                                    1) the array value was being looked up 3 times, it's faster to look it up once and then reuse that value.
                                    2) When accessing arrays sequentially it's better if the first subscript is used in the inner loop. This is because of the way arrays are stored in memory and results in sequential accesses to memory rather than random-ish access and allows the system to make more efficient use of the CPU caches.

                                    On my 1.8GHz Athlon your original array code takes 167ms, this now runs in 104ms, 40% faster than your original.

                                    Next, for your other loop, the ABS() function is very slow and you'd do better to avoid it if you can. Try changing your second loop to this:
                                    Code:
                                    FOR j&=0 TO 1039
                                       FOR i&=0 TO 1391
                                    '   var=var+ABS(sum-values(i&,j&))                         
                                        k&=sum-values(i&,j&)
                                        IF k&<0 THEN var=var-k& ELSE var=var+k&
                                      NEXT
                                    NEXT
                                    This now takes 45ms on mine and we haven't used pointers or ASM yet. Looks like sub 10ms may well be possible.

                                    Paul.

                                    ------------------

                                    Comment


                                    • #19
                                      Excellent observations, Paul. I've made the changes and also I tried
                                      the following pointer approach. It's about 1.24 times faster than
                                      the index approach. See any tricks one could play in the pointer approach?

                                      -CMR

                                      Code:
                                                                  sum=0
                                                                  var=0
                                                                  xsum=0
                                                                  ysum=0
                                                                  u&=0
                                                                  v&=0
                                                                  FOR i&=0 TO 1447679
                                                                      k&[email protected]
                                                                      sum=sum+k&
                                                                      IF u&<1392 THEN
                                                                          INCR u&
                                                                      ELSE
                                                                          u&=0
                                                                          INCR v&
                                                                      END IF
                                                                      xsum=xsum+u&*k&
                                                                      ysum=ysum+v&*k&
                                                                      INCR pValues
                                                                  NEXT
                                                                  xsum=xsum/sum
                                                                  ysum=ysum/sum
                                                                  sum=sum/1447679
                                                                  FOR i&=0 TO 1447679
                                                                      DECR pValues
                                                                      k&[email protected]
                                                                      IF k&<0 THEN var=var-k& ELSE var=var+k&
                                                                  NEXT
                                                                  var=var/1447679

                                      ------------------

                                      Comment


                                      • #20
                                        CMR,
                                        For that first loop I'd use 2 nested loops, not one loop.
                                        The work involved in splitting the one loop counter into u and v values is far freater than the extra loop overhead. You're comparing U& with 1392 and incrementing it over 1.4 million times. With 2 nested loops you'd save that 1.4 million IF..ENDIFs and replace them with the overhead of a for..next loop with about 1000 iterations.
                                        Something like this (untested):
                                        Code:
                                        sum=0
                                        var=0
                                        xsum=0
                                        ysum=0
                                        u&=0
                                        v&=0
                                        for u& = 0 to 1391
                                            for v& = 0 to 1039
                                                k&[email protected]
                                                sum=sum+k&
                                                xsum=xsum+u&*k&
                                                ysum=ysum+v&*k&
                                                INCR pValues
                                            next
                                        next
                                        xsum=xsum/sum
                                        ysum=ysum/sum
                                        sum=sum/1447679
                                        FOR i&=0 TO 1447679
                                            DECR pValues
                                            k&[email protected]
                                            IF k&<0 THEN var=var-k& ELSE var=var+k&
                                        NEXT
                                        var=var/1447679
                                        I've never checked if it works, but can you not repla "FOR i&=0 TO 1447679" with "FOR pValue=startValue to EndValue" and you then wouldn't need an explicit INCR/DECR pValue in the loop?


                                        Other than that, your code is being slowed down by the use of QUAD and DWORD values. QUADs in particulaer tend to be slow.
                                        I can't say whether or not you can manipulate the data in order to fit it all in LONGs as it will probably cause a loss of accuracy and I don't know whether that would be acceptable for your application.

                                        Paul.

                                        ------------------

                                        Comment

                                        Working...
                                        X