Das OFFIZIELLE PROFAN SUPPORT FORUM
Einsteigerfragen
PROFAN-Programmierung
Helfer & Tools
Anregungen & Vorschläge
PROFAN-NEWS
Die Regeln!
2 - PROFAN-Programmierung

 Neues Thema  |  Zur Übersicht  |  Suchen  |  Einloggen   Neuerer Beitrag  |  Älteres Thema 
 Multiprozessing mag keinen Inline-Assembler
Autor: Arndt Lindner (---.dip0.t-ipconnect.de)
Datum:   06.10.18 17:09

Inline-Assembler-Routinen werden bei einem Aufruf mit PExec/PExecWait nicht gefunden (Fehlermeldung: Funktion unbekannt: MUL64 ).
Codebeispiel (XProfanX4):
 struct complex = a!,b!
 
 ' Bildung von Complex (a,b)
 proc c_build_ab
 parameters double za, zb
 declare memory rw : dim rw, complex
   float rw,0 = za
   float rw,8 = zb
   return rw
 endproc
 
 ' Multiplikation in Assembler
 ASM "Mul64", 2
    JMP Start
 Ergebnis_Re:
    DQ 0
 Ergebnis_Im:
    DQ 0
 Start:
    MOV EAX, par1
    MOV EBX, par2
    FLD QWORD PTR [EAX]
    FLD QWORD PTR [EBX]
    FMUL
    FLD QWORD PTR [EBX+8]
    FLD QWORD PTR [EAX+8]
    FMUL
    FSUB
    FSTP QWORD PTR [Ergebnis_Re]
    FLD QWORD PTR [EAX+8]
    FLD QWORD PTR [EBX]
    FMUL
    FLD QWORD PTR [EBX+8]
    FLD QWORD PTR [EAX]
    FMUL
    FADD
    FSTP QWORD PTR [Ergebnis_IM]
    MOV EAX, Ergebnis_RE
 ENDASM
 
 proc c_mulass
 parameters memory zx1,zx2
 declare pointer P
    P = Mul64(zx1,zx2)
    return c_build_ab(Float(P,0),Float(p,8))
 endproc
 
 ' Multiplikation in XProfanX4
 proc c_mul
 parameters memory zx1, zx2
   return c_build_ab(float(zx1,0)*float(zx2,0) - float(zx1,8)*float(zx2,8), float(zx1,0)*float(zx2,8) + float(zx1,8)*float(zx2,0))
 endproc
 
 ' Ausgabeformatierung
 proc c_str
 parameters memory zx1
   return "("+format$("%e",float(zx1,0))+","+format$("%e",float(zx1,8))+")"
 endproc
 
 proc berechnung
 parameters string Filemapname, rea, ima
 struct complex = a!, b!
 declare memory zi : dim zi, complex
 declare memory ci_feld : dim ci_feld,100
 declare handle fmhnd
   fmhnd = FileMap("Open",Filemapname)
   ci_feld = FileMap("Map",fmhnd)
   zi = c_build_ab(val(rea),val(ima))
   zi = c_mul(zi,zi)
   float ci_feld,0 = float(zi,0)
   float ci_feld,8 = float(zi,8)
   Filemap("Close",fmhnd)
   dispose ci_feld
   dispose zi
 endproc
 
 proc berechnungass
 parameters string Filemapname, rea, ima
 struct complex = a!, b!
 declare memory zi : dim zi, complex
 declare memory ci_feld : dim ci_feld,100
 declare handle fmhnd
   fmhnd = FileMap("Open",Filemapname)
   ci_feld = FileMap("Map",fmhnd)
   zi = c_build_ab(val(rea),val(ima))
   zi = c_mulass(zi,zi)
   float ci_feld,0 = float(zi,0) 
   float ci_feld,8 = float(zi,8)
   Filemap("Close",fmhnd)
   dispose ci_feld
   dispose zi
 endproc
 
 ' Hauptprogramm
 
 declare memory c_feld : dim c_feld,100
 declare memory zn : dim zn, complex
 declare handle fmhnd, thnd1, thnd2
 
   WindowTitle "Test"
   WindowStyle 15
   Window 10,10-600,300
 
 Set("AsmMode", 0)
 fmhnd = create("FileMap","Feld",100)
 c_feld = FileMap("Map",fmhnd)
 
 print "Test im Hauptprozess ohne Assembler"
   clear c_feld
   berechnung("Feld","2.8","7.5")
   print c_str(c_feld)
 
 print "Test im Hauptprozess mit Assembler"
   clear c_feld
   berechnungass("Feld","2.8","7.5")
   print c_str(c_feld)
 
 print "Test im Parallelprozess ohne Assembler"
   clear c_feld
   thnd1 = PExecWait("|berechnung","Feld","2.8","7.5")
   print c_str(c_feld)
 
 Print "Test im Parallelprozess mit Assembler"
   clear c_feld
   thnd2 = PExecWait("|berechnungass","Feld",2.8,7.5)
   print c_str(c_feld)
 
 FileMap("Close",fmhnd)
 dispose zn
 dispose c_feld
 waitinput
 end
 

Der Code ist aus einem größeren Projekt "herausgekürzt" aber immer noch ziemlich lang.
Geht das nicht oder mache ich etwas falsch?

Beitrag beantworten
 
 Re: Multiprozessing mag keinen Inline-Assembler
Autor: Michael Wodrich (---.customer.vsm.sh)
Datum:   07.10.18 20:34

Eine ASM-Routine wird beim ersten Erscheinen im Code registriert, bekommt also einen Eintrag in einer Funktionsliste der externen Prozedoren/Funktionen.

Das dürfte Problem Nummer eins sein. Alle weiteren Aufrufe werden diese Adresse nicht finden.

Und das zweite Problem ist: Wie soll das System beim Multitasking den FPU-Stack absichern?

Ich glaube, das ist nicht so ganz einfach.

--
Programmieren, das spannendste Detektivspiel der Welt.
Programmierumgebung: | XProfan (neueste) | Win (neueste)


Beitrag beantworten
 
 Re: Multiprozessing mag keinen Inline-Assembler
Autor: Heinz Brill (---.dip0.t-ipconnect.de)
Datum:   08.10.18 07:54

Das Hauptproblem dürfte wohl sein, daß einem Prozess,
der mit pExec aufgerufen worden ist, die Funktionsliste
der ext. Funktionen nicht bekannt ist. Das scheint nur
mit den profaninternen Funktionen /Procs zu gehen.

Die gleiche Fehlermeldung kommt ja auch, wenn man
im Hauptprogramm eine DLL mit ImportDLL einbindet
und versucht, in einer per PExec aufgerufenen Proc
die DLL-Funktionen dort zu nutzen.

Da müßte man mal Roland fragen, ob er prozessübergreifend
bzw. modulübergreifend die Funktionsliste bekannt geben kann.

Gerade bei den Prozess("",...) Funktionen, müßten dann
z.B. bei Prozess("Kill",....) die DLL-Funktionen nicht immer
wieder neu initialisiert werden.


Das gleiche Spiel ist dann auch mit den selbst erstellten
Container-Funktionen.

H.Brill
XProfan X4 + FreeProfan

Nachricht bearbeitet (08.10.18 08:00)

Beitrag beantworten
 
 Re: Multiprozessing mag keinen Inline-Assembler
Autor: Arndt Lindner (---.dip0.t-ipconnect.de)
Datum:   08.10.18 10:50

Vielen Dank an Michael und Heiz für die erklärenden Antworten.
Ich glaube, dass mein Problem mit mehreren parallel laufenden eigenständigen Programmen gelöst werden kann.
In meinem Projekt wil ich Phasenbilder meromorpher Funktionen berechnen. Den nicht unerheblichen Rechenaufwand will ich halt mit Assemblerroutinen und paralleler Verarbeitung auf mehreren Kernen in erträglichen Grenzen halten.
Also nochmals vielen Dank.

Beitrag beantworten
 
 Re: Multiprozessing mag keinen Inline-Assembler
Autor: Heinz Brill (---.dip0.t-ipconnect.de)
Datum:   08.10.18 14:04

Vielleicht könntest du das Problem lösen, indem du einen
kleinen Workaround nutzt :

Mach mal die ASM-Proc in eine Include-Datei und includiere sie
jeweils in den einzelnen Prozessen, in denen du sie aufrufst.
Wäre ja dann nur ein einzelnes $I meine.inc in jedem Prozess.

Bei DLL's scheint das jedenfalls zu funktionieren. Ich denke mal,
daß das bei den ASM-Procs genauso ist, weil die in der gleichen
Funktionsliste stehen.

H.Brill
XProfan X4 + FreeProfan

Beitrag beantworten
 
 Re: Multiprozessing mag keinen Inline-Assembler
Autor: Arndt Lindner (---.dip0.t-ipconnect.de)
Datum:   08.10.18 19:47

Habe ich bereits gemacht und es funktioniert jetzt. Dabei musste ich dafür sorgen, dass in der Includedatei mit der komplexen Arithmetik die Assemblerroutine jeweils einen eigenen Namen bekommt. Es sieht jetzt folgendermaßen aus:
Includeroutine:
 $IFDEF var0
 ASM "Mul640", 2
 $ENDIF
 $IFDEF var1
 ASM "Mul641", 2
 $ENDIF
 $IFDEF var2
 ASM "Mul642", 2
 $ENDIF
 $IFDEF var3
 ASM "Mul643", 2
 $ENDIF
 $IFDEF var4
 ASM "Mul644", 2
 $ENDIF
    JMP Start
 ...
 ENDASM
 
 // eigentliche Multiplikationsroutine
 proc c_mul
 parameters memory zx1,zx2
 declare pointer P
 $IFDEF var0
   P = Mul640(zx1,zx2)
 $ENDIF
 $IFDEF var1
   P = Mul641(zx1,zx2)
 $ENDIF
 $IFDEF var2
   P = Mul642(zx1,zx2)
 $ENDIF
 $IFDEF var3
   P = Mul643(zx1,zx2)
 $ENDIF
 $IFDEF var4
   P = Mul644(zx1,zx2)
 $ENDIF
    return c_build_ab(Float(P,0),Float(p,8))
 endproc
 

Damit kann ich in allen 5 Programmen (ein Hauptprogramm und bis zu vier parallele Berechnungsprogramme) die Funktion mit "c-mul(p1,p2)" aufrufen. Ich muss nur in jedem der Programme die Variable "varx" unterschiedlich mit $DEFINE festlegen. Im Endeffekt wird für jedes Programm eine anderer Includedatei bei der Compilierung erzeugt.
Der Umweg über varx vermeidet jegliche Pflege unterschiedlicher Includedateien bzw. Verwendung unterschiedlicher Funktionsnamen in der Umgebung der Bibliothek.

Beitrag beantworten
 
 Re: Multiprozessing mag keinen Inline-Assembler
Autor: Heinz Brill (---.dip0.t-ipconnect.de)
Datum:   09.10.18 16:37

Ginge das mit einem Namensraum nicht eleganter ?
In der Include :

 ASM "Mul64", 2
     JMP Start
  Ergebnis_Re:
     DQ 0
  Ergebnis_Im:
     DQ 0
  Start:
     MOV EAX, par1
     MOV EBX, par2
     FLD QWORD PTR [EAX]
     FLD QWORD PTR [EBX]
     FMUL
     FLD QWORD PTR [EBX+8]
     FLD QWORD PTR [EAX+8]
     FMUL
     FSUB
     FSTP QWORD PTR [Ergebnis_Re]
     FLD QWORD PTR [EAX+8]
     FLD QWORD PTR [EBX]
     FMUL
     FLD QWORD PTR [EBX+8]
     FLD QWORD PTR [EAX]
     FMUL
     FADD
     FSTP QWORD PTR [Ergebnis_IM]
     MOV EAX, Ergebnis_RE
  ENDASM
 
  proc c_build_ab
  parameters double za, zb
  declare memory rw : dim rw, complex
    float rw,0 = za
    float rw,8 = zb
    return rw
  endproc
 
 proc ?_c_mul
 parameters memory zx1,zx2
 declare pointer P
  P = Mul64(zx1,zx2)
  return c_build_ab(Float(P,0),Float(p,8))
 endproc
 


und in den einzelnen Prozessen halt

 $I meineinc.inc = irgendwas_
 
 Ergebnis = irgendwas_c_mul(ber1, ber2)
 


Sowas wäre doch übersichtlicher.

PS:
Was schreibst du denn genau in die FileMap ?

Wenn das nur zwei Zahlen sind, geht das auch einfacher mit
SendMessage in den Prozessen. Die Zahlen bekommt man in
wParam und lParam ja unter. Du mußt nur bei pExec der Proc's
das Handle deines Hauptfensters (%HWnd) mitgeben.

Im Hauptprogramm definierst du eine Usermessage und fragst
sie in der Ereignisschleife ab (%UMessage) . In den Prozessen
kannst du dann mit
SendMessage(übergebenesFenster, Message, wParam, lParam)
dein Hauptprogramm informieren. Das ist auch interessant, wenn
man nicht weiß, wann ein Prozess fertig ist. Dieser informiert bei
Fertig das Hauptfenster und gibt noch ggf. 2 Long-Parameter mit.

H.Brill
XProfan X4 + FreeProfan

Nachricht bearbeitet (09.10.18 17:05)

Beitrag beantworten
 
 Re: Multiprozessing mag keinen Inline-Assembler
Autor: Arndt Lindner (---.dip0.t-ipconnect.de)
Datum:   09.10.18 19:11

Die Idee sieht sehr gut aus. Ich werde es probieren. Das Problem ist nicht der Name von c_mul sondern der Name der Assemblerroutine. Ich müsste dann das Alias vor Mul64 schreiben. Wie gesagt, ich werde es ausprobieren, da es tatsächlich eleganter ist.
In der Bitmap steht ein Feld von z.B. 900x900x2 Double-Zahlen (bei einer Bildgröße von 900x900 Pixel) plus zukünftig einige Organisationsdaten auf die mehrere Programme zugreifen. Das Gesamtpaket soll zukünftig automatisch auf die Anzahl der vorhandenen Rechnerkerne skalieren. Ich denke, eine Bitmap ist dafür das geeignete Mittel. Das Beispiel war nur entsprechend abgespeckt.
Tests mit der jetzt lauffähigen Version haben mit den Assemblerroutinen eine Beschleunigung um ca. 10% gebracht (Prozessor: i5-7400, 16 GB RAM) . Dabei habe ich zur Zeit nur die Multiplikation und die Division in Assembler umgesetzt.

Beispiele für die zu berechnenden Bilder findet man hier:
https://www.mathe.tu-freiberg.de/~wegert/Lehre/FkthSpez/Clips/Section0/Clip-0-2.pdf

Beitrag beantworten
 
 Re: Multiprozessing mag keinen Inline-Assembler
Autor: Heinz Brill (---.dip0.t-ipconnect.de)
Datum:   09.10.18 19:46

Normalerweise müßte doch die ASM-Proc auch ohne Namensraum
funktionieren. Die wurde ja nur nicht im Prozess gefunden, da
sie in Rolands Funktionsliste nur dem Hauptprogramm bekannt
ist. Bei der Include sieht es ja anders aus. Nötigenfalls könntest
du mal versuchen, die ASM-Proc nochmals in eine Proc zu packen.
Also so :

 Proc c_mul
 Parameters Memory zx1,zx2
 Declare Pointer p
 
 ASM "Mul64", 2
 ….
 EndASM
 p = Mul64(zx1, zx2)
 return c_build_ab(Float(P,0),Float(p,8))
 EndProc
 
 proc c_build_ab
   parameters double za, zb
   declare memory rw : dim rw, complex
     float rw,0 = za
     float rw,8 = zb
     return rw
 endproc
 

Wäre evtl. auch einen Versuch wert.

H.Brill
XProfan X4 + FreeProfan

Beitrag beantworten
 Foren-Liste  |  Baumstruktur   Neuerer Beitrag  |  Älteres Thema 


 Foren-Liste  |  Zur Registrierung 
 Benutzerlogin
 Benutzername:
 Passwort:
 Login-Daten speichern:
   
 Passwort vergessen?
E-Mail-Adresse oder Username unten eingeben. Dann wird Dir per e-Mail ein neues Passwort zugeschickt.

phorum.org