Kann man einem Thread eine CPU zuordnen??? Bsp. Primberechnung



  • Hallo Leute,
    ich habe Stunden gesucht und keine Antwort gefunden.
    Angenommen man hat ein Programm in dem man zwei oder mehrere
    Threads hat, kann man dann, um den bspw. Dualcore Prozessor
    komplett auszulasten, einem Thread die eine und dem anderen Thread
    die andere CPU zuweisen?

    Eine Beispielanwendung in der es auch keine Ressourcenkonflikte geben dürfte,
    wäre die berechnung von Primzahlen.
    Die Aufteilung die ich vornehmen würde wäre, dass jeweils ein Thread
    eine Zahl prüft.

    Ich habe schon von anderen Verfahren wie OpenMP gelesen, jedoch
    will ich wissen ob man auch einem Thread manuel eine CPU zweisen kann?

    Vielen Dank im Voraus für eure Antworten...

    rom4o 🙂



  • Das ist grundsätzlich Sache des Betriebssystems. Alles was du machen mußt ist mehrere Threads zu erstellen (z.B. so viele, wie CPUs/Cores vorhanden sind), und die sollten dann automatisch vom Scheduler sinnvoll verteilt werden.

    Es gibt zwar auch Mittel und Wege, Threads explizit einer bestimmten CPU zuzuweisen, in den allermeisten Fällen gibt es aber keinen Grund, das zu tun.





  • Hallo, perfekt, mit dem WinAPI Kommando
    funktioniert das wunderbar.
    Ich danke vielmals für eure Hilfe....#

    😃
    rom4o



  • Hallo Leute, ich bins nochmal. 😞
    Also wie schon gesagt der Befehl funktioniert.
    Aber nun ist ein neues Problem aufgetaucht.

    Ich zeichne in folgendem Programm, in zwei verschiedenen Threads,
    bunte Rechtecke ohne Sleep(), also so schnell wie nur möglich.

    Ich habe jedem Thread, mit dem Befehl
    SetThreadAffinityMask(), einen Kern meines Dualcore-Prozessors zugewiesen.

    Wenn man die Threads einzeln per Button startet sieht man im Tastkmanager
    wunderbar wie die einzelnen Kerne voll ausgelastet werden.
    Doch wenn ich beide Threads starte spielt Alles verrückt, die einzelnen
    Zeichenfortschritte werden falsch gezählt und die CPU-Auslastung bleibt
    insgesamt bei ca. 50% also jeder Core arbeitet dann nur noch zur Hälfte statt voll.

    Hier ist der komplette Code:

    #include "stdafx.h"
    #include <windows.h>
    
    #include <stdlib.h>
    //#include <winbase.h>
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
    DWORD WINAPI ThreadProc ( LPVOID);
    
    HWND hWindow,hButton;				//Modifikation
    char szBuffer[30] = { 0 };			//Modifikation
    
    int APIENTRY WinMain(HINSTANCE hInstance,
    					 HINSTANCE hPrevInstance,
    					 LPSTR lpCmdLine,
    					 int nCmdShow )
    {
    	WNDCLASS WndClass;
    	WndClass.style = 0;
    	WndClass.cbClsExtra = 0;
    	WndClass.cbWndExtra = 0;
    	WndClass.lpfnWndProc = WndProc;
    	WndClass.hInstance = hInstance;
    	WndClass.hbrBackground = (HBRUSH) (COLOR_WINDOW+1);
    	WndClass.hCursor = LoadCursor (NULL, IDC_ARROW);
    	WndClass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    	WndClass.lpszMenuName = 0;
    	WndClass.lpszClassName = "WinProg";
    
    	RegisterClass(&WndClass);
    
    //	HWND hWindow,hButton;		//wurde am Anfang des Programms wegen Sichtbarkeit deklariert
    
    	hWindow = CreateWindow("WinProg","Fenster",
    							WS_OVERLAPPEDWINDOW,
    							0,0,450,450,NULL,NULL,
    							hInstance, NULL);
    
    	hButton = CreateWindow("BUTTON","Start Thread 1",
    							WS_CHILD | WS_VISIBLE
    							| BS_PUSHBUTTON,
    							10,210,200,20,hWindow,
    							(HMENU) 1, hInstance, NULL);
    
    	hButton = CreateWindow("BUTTON","End Thread 1",
    							WS_CHILD | WS_VISIBLE
    							| BS_PUSHBUTTON,
    							10,240,200,20,hWindow,
    							(HMENU) 2, hInstance, NULL);
    
    	hButton = CreateWindow("BUTTON","Start Thread 2",
    							WS_CHILD | WS_VISIBLE
    							| BS_PUSHBUTTON,
    							10,290,200,20,hWindow,
    							(HMENU) 3, hInstance, NULL);
    
    	hButton = CreateWindow("BUTTON","End Thread 2",
    							WS_CHILD | WS_VISIBLE
    							| BS_PUSHBUTTON,
    							10,320,200,20,hWindow,
    							(HMENU) 4, hInstance, NULL);
    
    	ShowWindow (hWindow, nCmdShow);
    	UpdateWindow (hWindow);
    	MSG Message;
    	while (GetMessage(&Message, NULL, 0, 0))
    	{
    		DispatchMessage(&Message);
    	}
    	return (Message.wParam);
    }
    
    DWORD WINAPI ThreadProc1( LPVOID pvoid )
    {
    	int i1 = 0;														//Modifikation
    	HBRUSH hBrush;													//Modifikation
    	HBRUSH hBrushalt;												//Modifikation
    
    	int wert = 2;
    	while (wert == 2)
    	{
    		HDC hdc1;
    		hdc1 = GetDC (hWindow);
    
    		hBrush = CreateSolidBrush (RGB(rand()%255,rand()%255,rand()%255));
    		hBrushalt = (HBRUSH) SelectObject (hdc1, hBrush);
    
    		Rectangle (hdc1 ,rand()%200 ,rand()%200 ,rand()%200, rand()%200);
    
    //		Sleep(20);													//Modifikation
    		i1++;														//Modifikation
    		wsprintf( szBuffer , "%10d", i1);							//Modifikation
    //		SetTextColor (hdc1, RGB(0,0,180));							//Modifikation
    //		SetBkColor (hdc1, RGB(190,180,200));						//Modifikation
    		TextOut (hdc1, 310, 50, szBuffer, lstrlen(szBuffer));		//Modifikation
    
    		ReleaseDC (hWindow, hdc1);
    		DeleteObject(hBrush);										//Modifikation
    	}
    
    	DeleteObject(hBrushalt);										//Modifikation
    	return NULL;													//notwendige Modifikation
    }
    
    DWORD WINAPI ThreadProc2( LPVOID pvoid )
    {
    	int i2 = 0;														//Modifikation
    	int k = 250; int l = 100;
    	HBRUSH hBrush;													//Modifikation
    	HBRUSH hBrushalt;												//Modifikation
    
    	int wert = 2;
    	while (wert == 2)
    	{
    		HDC hdc2;
    		hdc2 = GetDC (hWindow);
    
    		hBrush = CreateSolidBrush (RGB(rand()%255,rand()%255,rand()%255));
    		hBrushalt = (HBRUSH) SelectObject (hdc2, hBrush);
    
    		Rectangle (hdc2 ,k + rand()%l ,k + rand()%l ,k + rand()%l,k + rand()%l);
    
    //		Sleep(20);													//Modifikation
    		i2++;														//Modifikation
    		wsprintf( szBuffer , "%10d", i2);							//Modifikation
    //		SetTextColor (hdc2, RGB(0,0,180));							//Modifikation
    //		SetBkColor (hdc2, RGB(190,180,200));						//Modifikation
    		TextOut (hdc2, 310,70, szBuffer, lstrlen(szBuffer));		//Modifikation
    
    		ReleaseDC (hWindow, hdc2);
    		DeleteObject(hBrush);										//Modifikation
    	}
    
    	DeleteObject(hBrushalt);										//Modifikation
    	return NULL;													//notwendige Modifikation
    }
    
    LRESULT CALLBACK WndProc (HWND hWnd, UINT uiMessage,
    						  WPARAM wParam,LPARAM lParam)
    {
    	static HANDLE hThread1;
    	static HANDLE hThread2;
    
    	switch(uiMessage)
    	{
    		case WM_PAINT:
    		{
    			HDC hdc;
     			PAINTSTRUCT ps;
    
    			hdc = BeginPaint (hWnd, &ps);							//BEGIN PAINT
    			TextOut (hdc, 210, 50, "ThreadProc1:", lstrlen("ThreadProc1:"));
    			TextOut (hdc, 210, 70, "ThreadProc2:", lstrlen("ThreadProc2:"));
    			EndPaint (hWnd, &ps);									//END PAINT
    			return 0;
    		}
    
    		case WM_COMMAND:
    			if (HIWORD(wParam) == BN_CLICKED)
    			{
    				if (LOWORD(wParam) == 1)
    				{
    					DWORD dwThreadParam1 = 1;
    					DWORD dwThreadID1;
    					hThread1 = CreateThread (NULL, 0, ThreadProc1,
    											&dwThreadParam1, 0, &dwThreadID1);
    					SetThreadAffinityMask(hThread1, 1);
    						//SetProcessorAffinityMask
    				}
    
    				if (LOWORD(wParam) == 2)
    				{
    					TerminateThread (hThread1, 0);
    				}
    
    				if (LOWORD(wParam) == 3)
    				{
    					DWORD dwThreadParam2 = 2;
    					DWORD dwThreadID2;
    					hThread2 = CreateThread (NULL, 0, ThreadProc2,
    											&dwThreadParam2, 0, &dwThreadID2);
    					SetThreadAffinityMask(hThread2, 2);
    						//SetProcessorAffinityMask
    				}
    
    				if (LOWORD(wParam) == 4)
    				{
    					TerminateThread (hThread2, 0);
    				}
    			}
    			return 0;
    
    		case WM_DESTROY:
    			PostQuitMessage(0);
    			return 0;
    
    		default:
    			return DefWindowProc (hWnd, uiMessage, wParam, lParam);
    	}
    }
    

    **
    Ich hoffe ihr könnt mir einen Rat geben, ich weiss echt nicht voran es liegt.
    Meiner Meinung nach greifen die Threads jeweils auf nur die eigenen Ressourcen zu,
    wodurch es keine Konflikte geben dürfte.
    Ich habe ja auch das Programm geschrieben um mal mit Mutlithreading den Prozessor voll
    auszulasten, aber wieder nur halbe Last....woran liegts????

    Vielen Dank für alle Ratschläge.....

    rom4o**



  • Ich kenne mich jetzt mit dem Win-API nicht sonderlich gut aus, aber wenn ich das richtig sehe, zeichnest du doch mit 2 Threads in dem selben Fenster. Selbst wenn Windows das erlauben sollte (mag sein) ist das sicher nicht das, was ich unter "nur eigene Ressourcen" verstehen würde.

    In der Regel würde man nur genau einen Thread zum Zeichnen benutzen, alle anderen Threads kümmern sich um Berechnungen im Hintergrund. Und das ganze natürlich, da wo es nötig ist, abgesichert über Mutexes o.ä.

    Außerdem frage ich mich nach wie vor, ob du SetThreadAffinityMask überhaupt brauchst. Benutzt das Betriebssystem nicht automatisch beide Kerne?



  • Hallo, danke erstmal für die Antwort.
    Naja also erstmal besteht ja das Programm aus 3 Threads.
    Dem Fenster selber und den beiden expliziten Threads.

    ...zeichnest du doch mit 2 Threads in dem selben Fenster.

    Das stimmt schon, aber ich weiss nicht wie man das anders lösen könnte?

    In der Regel würde man nur genau einen Thread zum Zeichnen benutzen, alle anderen Threads kümmern sich um Berechnungen im Hintergrund.

    Das Problem ist, in diesem Programm gibts nix zu berechnen, alle Threads zeichnen.

    Und zu der Frage ob Windows beide Kerne automatisch nutzt, ja das tut es,
    aber leider nur beide Kerne mit halber statt voller Auslastung.

    Also irgendwie komme ich hier nicht weiter.
    Bitte um weitere Ratschläge....

    rom4o 😕



  • rom4o schrieb:

    Das Problem ist, in diesem Programm gibts nix zu berechnen, alle Threads zeichnen.

    Deshalb würde man hier auch keine Threads verwenden.

    Um den Umgang mit Threads zu lernen mach lieber etwas sinnvolles:
    http://de.wikipedia.org/wiki/Speisende_Philosophen



  • rom4o schrieb:

    Und zu der Frage ob Windows beide Kerne automatisch nutzt, ja das tut es, aber leider nur beide Kerne mit halber statt voller Auslastung.

    Ich glaube nicht, dass das immer der Fall ist...
    Das Problem wird also wo anders liegen (vll schreibst du in bestimmte Dateien oder wartest auf Events/Mutexe/... oder bestimmte Funktionen die du aufrufst rufen wiederrum wieder andere Funktionen aus, die aber in anderen Threads laufen...)
    Da irgendetwas also offenbar dein Programm stärker begrentzt als deine beiden CPU`s wirst du nicht drum rum kommen mal zu überlegen/suchen, was es ist.
    Allg. bleibt aber zu sagen, dass man mit mehrern Threads die gleiche Operationen ausführen in der Praxis wohl nie auf (jeweils) 100% CPU-Auslastung kommen werden - und selbst, wenn sie die CPU zu 100% nutzen bleibt ja der Overhead durch das Thread erstellen, starten, ... erhalten (wobei hier ja die CPU voll ausgelastet sein kann aber trotzdem dein eigtl Problem kaum in der Hälfte der Zeit bearbeitet werden kann).

    Bsp.:
    Was macht TextOut ?

    bb

    PS:
    #include <stdlib.h>
    ersetz das mal mit
    #include <cstdlib>
    So heißt der richtige Header (jetzt bzw. seit 10 Jahren)^^

    int wert = 2;
        while (wert == 2)
        {
             /*...*/
        };
    

    Ist aber schon ein wenig hässlich, oder?! ^^

    Wenn man dann noch so was hier sieht:
    i1++;
    Was in jedem Schleifendurchlauf aufgerufen wird, dann stellt sich mir doch erst recht die Frage, warum du keine for-Schleife nimmst...

    char szBuffer[30] = { 0 };
    
    /*...*/
    
    wsprintf( szBuffer , "%10d", i1);
    

    Warum kein std::string?
    Übrigens sieht das so aus, als ob du 2 strings bräuchtest - einen pro Thread...

    Und die ganzen Pointer, die du jedes mal free`en und deleten musst sind auch komisch - gibts keine Möglichkeit, da den Stack zu nutzen (hat den Nebeneffekt, dass man sich nicht nur Quellcode spart, sondern es auch noch (sehr viel) schneller sein sollte ^^)

    Bleibt also zu fragen:
    Warum das C++ - Forum?
    1. Ist es Win-API (hatten wir ja schon geklärt ^^)
    2. Ist es C

    Naja - bb ^^



  • Hallo,
    natürlich ist das nicht immer der Fall, dass Windows beide Kerne nur halb auslastet,
    das ist halt nur hier in meinem Programm leider immernoch der Fall.

    Also die Sache mit dem "szBuffer" habe ich total übersehen, da diese Variable
    gleich am Anfang global initialisiert wurde und von beiden Threads verwendet wurde
    gab es diesen Fehler, mit den verwirrten Zählerständen.
    Da hat man gleich mal gesehen was passiert wenn zwei oder mehrere Threads die
    selbe Ressource nutzen. Das hört sich vielleicht blöd an, aber für mich ist
    Multithreading totales Neuland und in sofern interessant.

    Verstehe die Frage bezüglich Textout nicht???
    Und was soll immer dieses "bb" bedeuten, ist glaub keine offizienlle Abkürzung?
    bb = blabla oder was 😃 ....naja

    #include <stdlib.h>
    ersetz das mal mit
    #include <cstdlib>
    So heißt der richtige Header (jetzt bzw. seit 10 Jahren)^^

    Und um mich zu verteidigen, der folgende Code

    int wert = 2;
        while (wert == 2)
        {
             /*...*/
        };
    

    ist nicht von mir sondern aus einem Buch Seite 150
    --->>> Henning Hansen
    Windows-Programmierung
    mit C++
    339 Seiten
    ISBN 3-8273-1747-9

    habe aber das e-book.

    Ich hätte den Code natürlich auch anders gestalltet, doch ich wollte vorerst nur
    das nötigste modifizieren um mein Ziel zu erreichen.
    Das erklärt wohl auch den veralteten Header <stdlib.h>, das Buch ist schon etwas betagt.

    Warum kein std::string?

    Sorry aber ich kenne diese Notation garnicht. Ist die nicht aus den MFC?

    Und die ganzen Pointer, die du jedes mal free`en und deleten musst
    sind auch komisch - gibts keine Möglichkeit, da den Stack zu nutzen
    (hat den Nebeneffekt, dass man sich nicht nur Quellcode spart, sondern
    es auch noch (sehr viel) schneller sein sollte ^^)

    Tja, hab mir auch schon sowas gedacht, aber ich weiss nicht wie ich das in C++ implementiere,
    kann das nur in Java. Vielleicht kannst du mir da ja einen konkreten Codetip geben 🙂 ?

    Achja und zu der Win-API-Forum-Sache.... das hat sich leider erst so entwickelt, da ich zuerst nicht
    wusste wo es genau reingehört, sorry....

    @Admin : villeicht kann der das ja verschieben.....?

    @unskilled : Übrigens glaube ich, dass du deinen Namen zu unrecht trägst.

    @Shade Of Mine : hab mir das Philosophenproblem angeschaut, sehr anschaulich.

    Also bin weiterhin dankbar für Ratschläge, die Sache mit den Stacks könnte
    es wirklich beschleunigen, weiss aber nicht wie?

    grüße rom4o



  • rom4o schrieb:

    Also bin weiterhin dankbar für Ratschläge, die Sache mit den Stacks könnte
    es wirklich beschleunigen, weiss aber nicht wie?

    Genauso wie du primitive Datentypen in Java anlegst (also z.B. int und float statt Integer und Float)

    // Java:
    int x = 0;
    float y = 0; 
    String z = new String();
    
    // cpp Stack
    #include <string>      // fuer cpp String
    
    int x = 0;
    float y = 0; 
    std::string z = "";    // Gegenstück zum Java String
    
    // heap
    std::string str* = new std::string();   // Speicher für String auf dem heap anfordern
    delete str;  // Speicher wieder freigeben
    

    Also einfach kein new verwenden und die Variablen wie primitive Datentypen behandeln.



  • Was denn nun?
    Was willst du programmieren?

    C oder C++ ?

    Ich hab mal paar Sekunden gegoogelt: hBrush bekommt man imho nicht so einfach auf den Stack - die WinAPI bietet diese Funktionalität offenbar nicht...

    zu TextOut:

    char szBuffer[30] = { 0 };
    wsprintf( szBuffer , "%10d", i1);
    TextOut (hdc2, 310,70, szBuffer, lstrlen(szBuffer));
    
    //wird zu:
    
    #include <string>
    std::string Buffer1;
    std::string Buffer2; //für anderen Thread - besser auch lokal in den Threads deklarieren - oder brauchste das unbedingt global? Oo
    
    Buffer1 = ToStr(i1); //für Umwandlung siehe FAQ
    
    TextOut (hdc2, 310, 70, Buffer1.c_str(), Buffer1.length());
    
    Rectangle (hdc1 ,rand()%200 ,rand()%200 ,rand()%200, rand()%200);
    

    Was willst du hier machen?
    Ich hab beim googlen nut das .NET-Rechteck gesehen - aber das würde keinen passenden CTor haben...

    bb (bye bye / bis bald / ...) - siehe dazu auch (musst bissl suchen ^^):
    http://abkuerzungen.de/result.php?searchterm=bb&language=de&style=standard&x=31&y=2



  • Dein code ist schrecklich, z.b. wie du aus zwei Threads lustig irgendwelche brushes ins fenster rein selektierst, ohne dabei irgendwas zu synchronisieren.

    Davon abgesehen: der Grund warum du nicht über 50% CPU Auslastung kommst, ist, dass nicht zwei Threads gleichzeitig irgendwas in ein Fenster zeichnen können. Das "ist einfach so", daran kannst du nichts ändern.

    Würdest du, wie du ursprünglich geschrieben hast, bloss Primzahlen berechnen, dann würdest du auch eine CPU Auslastung von 100% sehen.

    Und vergiss bitte was hier über Stack/Blah geschrieben wurde, das tut hier überhaupt nichts zur Sache.



  • hustbaer schrieb:

    Und vergiss bitte was hier über Stack/Blah geschrieben wurde, das tut hier überhaupt nichts zur Sache.

    imho tut es das doch - weil auf den stack idR schneller zugegriffen werden kann - und spätestens wenn man den heap zugemüllt hat und die auslagerungsdatei herhalten muss ist das 100%ig der flaschenhals und sorgt dann auch dafür, dass das programm nicht auf seine 100% CPU-Auslastung kommt - aber ok - idR wird es durch diesen Unterschied einfach (nur) ein wenig langsamer

    hustbaer schrieb:

    der Grund warum du nicht über 50% CPU Auslastung kommst, ist, dass nicht zwei Threads gleichzeitig irgendwas in ein Fenster zeichnen können.

    wo hast du gelesen, dass die fkt thread-safe ist? war auch mein erster gedanke aber ich habs nirgendwo auf die schnelle finden können ^^

    bb



  • imho tut es das doch - weil auf den stack idR schneller zugegriffen werden kann - und spätestens wenn man den heap zugemüllt hat und die auslagerungsdatei herhalten muss ist das 100%ig der flaschenhals und sorgt dann auch dafür, dass das programm nicht auf seine 100% CPU-Auslastung kommt - aber ok - idR wird es durch diesen Unterschied einfach (nur) ein wenig langsamer

    Heap-Allokationen sind zeitraubend, ja. Der Zugriff ist dann aber grundsätzlich gleich schnell wie auf den Stack. Tut aber hier trotzdem nichts zur Sache, da es in dem Code keine expliziten Heap-Allokationen gibt. Die GDI Objekte die er verwendet muss man immer über die diversen WinAPI Funktionen verwalten, das geht nicht anders.

    wo hast du gelesen, dass die fkt thread-safe ist?

    Ich habe nichts von thread-safe geschrieben.
    Ich kann dir auch keine Quelle angeben.
    Ich bin mir trotzdem sicher, dass man unter Windows nicht gleichzeitig auf den Bildschirm malen kann. Bei Funktionen wie TextOut kommt dann noch dazu, dass Windows hier einige interne Datenstrukturen verwendet (glyph cache z.B.). Hier muss Windows intern die Zugriffe synchronisieren.



  • Dieser Thread wurde von Moderator/in Phoemuex aus dem Forum C++ in das Forum WinAPI verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • Im Buch "Windowsprogrammierung" von Charles Petzold gibt es ein Kapitel 20 "Multitasking und Multithreading", dort gibt es einen Unterpunkt "Seiteneffekte":

    ...
    Es sieht so aus, als müsse der gleichzeitige Zugriff zweier Threads auf dasselbe Fenster durch einen kritischen Abschnitt verhindert werden. Experimente, die ich in diese Richtung angestellt habe, zeigen aber, dass Windows bei grafischen Zeichenfunktionen selbst für die Serialisierung sorgt: Zu jedem Zeitpunkt kann immer nur ein Thread in ein Fenster zeichnen. Ein Zweiter Thread, der da gleichzeitig versucht, bleibt so lange blockiert, bis der erste Thread seine Operationen abgeschlossen hat.

    Diese Aussage scheint zu erklären, warum die CPU Auslastung auf etwa die Hälfte beschränkt bleibt. Während der erste Thread zeichnet, wartet der zweite Thread und der entsprechende CPU Kern hat währenddessen nichts zu tun - die Auslastung sinkt.
    Ich habe das Programm bei mir zum Laufen gebracht, um zu sehen, wie es funktioniert. Hier mein Makefile:

    all:
    	mingw32-gcc main.c -o main.exe -mwindows
    

    Ich beobachte im Prinzip dasselbe Verhalten wie rom4o. Wenn ich beide Threads aktiviere, sinkt bei meinem Centrino Duo 1.8 GHz die CPU Auslastung auf etwa 30 Prozent. Wahrscheinlich habe ich langsameren Rechner/Grafikkarte und die beiden Threads müssen entsprechend länger warten...



  • Hallo Leute, erstmal Danke für die vielen Antworten,
    na ist ja auch ein aktuelles Thema.

    @unskilled
    Also der folgende Befehl

    Rectangle (hdc1 ,rand()%200 ,rand()%200 ,rand()%200, rand()%200);
    

    funktioniert wunderbar in der Version 6 von MS Visual C++,
    mit der arbeite ich nämlich. Ich weiss, die ist sehr alt schon 10Jahre
    aber ich fahre bis jetzt noch ganz gut damit, will mir aber ein
    aktuelles Visual Studio zulegen.

    Der Befehl funktioniert so
    Rectangle (hdc1 ,rect.left ,rect.top ,rect.right, rect.bottom);
    hdcl ist in meinem Fall das Zielobjekt, in das gezeichnet werden soll
    und die einzelnen Einträge werden mit zufälligen Zahlen zwischen 1-200 belegt.
    Dabei kann es auch sein, dass einige Rechtecke nicht gezeichnet werden, wenn
    left>right oder top>bottom ist, aber bei der Zahl an Rechtecken die gezeichnet werden ist das nicht wichtig.

    @hustbaer
    Hallo, ja ich weiss, dass ich nix synchronisiert habe, konnte das ja bis dato auch nicht. Aber ich befasse mich ja fortwährend mit dem Thema.
    Und zu den Primzahlen später.

    @Phoemux, danke sehr fürs verschieben des Threads.... 🙂

    @abc.w
    Sehr schön, dass es bei dir läuft und du es probiert hast.
    Damit wäre ja dann meine Frage geklärt.

    Schade...aber ich arbeite nun an
    meiner ursprünglichen Idee, das Programm zur Primzahlenberechnung.
    Die Singlecore Variante habe ich fertig und läuft mit halber CPU-Auslastung wie gewohnt.

    In der Dualcore-Variante möchte ich das Problem 3teilen,
    3 Threads, die ersten beiden prüfen wie schon gesagt die jeweils
    übernächste ungerade Zahl und bei "true" sollen die Ergebnisse in eine Queue.
    Aus dieser soll dann der dritte Thread lesen und die Ergebnisse zeichnen.

    Bis jetzt weiss ich noch nicht wie ich die Threads synchronisieren soll.
    Ich möchte das wie in folgendem Beispiel haben:
    ...
    35
    37prim angenommen Thread1 rechnet noch
    39 und Thread2 ist fertig aber soll auf Thread1 warten bis der mit 41 beginnt
    Nun, fangen beide Threads mit jeweils 41 und 43 an
    41prim angenommen Thread1 braucht länger dann soll
    43prim Thread2 sein Ergebnis erst in die Queue schreiben wenn 41 drin steht
    sonst ist die Reihenfolge falsch
    45
    47prim
    49
    ...

    Ich weiss, dass ich so nicht die 100%Auslastung erzielen werde aber auf jeden Fall mehr als 50%.
    Die Frage ist, wie ich den Einen auf den anderen Thread warten lasse und umgekehrt?
    Ich dachte mir vielleicht mit SetEvent() und einer "Wait Function" oder ähnlich.
    Vielleicht hat ja einer von euch Ahnung davon?

    Vielen Dank,

    bb rom4o ...



  • rom4o schrieb:

    Bis jetzt weiss ich noch nicht wie ich die Threads synchronisieren soll.
    Ich möchte das wie in folgendem Beispiel haben:
    ...
    35
    37prim angenommen Thread1 rechnet noch
    39 und Thread2 ist fertig aber soll auf Thread1 warten bis der mit 41 beginnt
    Nun, fangen beide Threads mit jeweils 41 und 43 an
    41prim angenommen Thread1 braucht länger dann soll
    43prim Thread2 sein Ergebnis erst in die Queue schreiben wenn 41 drin steht
    sonst ist die Reihenfolge falsch
    45
    47prim
    49
    ...

    mach doch einen problemerzeuger und einen lösungsempfänger. der erzeuger gibt die probleme der reihe nach raus. der empfämger nimmt sie auch ungeordnet an, aber sortiert sie vorm anzeigen, also der hält falsch eingereite lösungen einfach kurz zurück.

    rom4o schrieb:

    Ich weiss, dass ich so nicht die 100%Auslastung erzielen werde aber auf jeden Fall mehr als 50%.

    sag das nicht. nehmen wir an, du checkst primzahlen im bereich um eine milliarde per triel division. da sind die primzahlen schon selten. ca jede zwanzigste ist prim. und bei primzahlen machste 15000 divisionen. viell viele zahlen haben aber kleine teiler. und die sind praktisch sofort fertig. von deinen 20 prozessoren würden die meiste zeit 19 leer warten auf den einen glücklichen, der ne primzahl getroffen hat.
    deswegen sollen sich die anderen rugig beim problemversorger bedienen dürfen und schonmal vorauslaufen.



  • Hallo volkard,
    Danke sehr für die rasche Antwort.
    Stimmt das leuchtet ziehmlich ein. Was du da vorschlägst fordert natürlich
    eine ganz neue Struktur meines Programms.
    Abgesehen davon habe ich noch keine Ahnung, wie ich die Geschichte mit den Threads händeln werde.
    Jedoch scheint mir dein Vorschlag sehr viel effektiver zu sein, als mein Ansatz. 🙂
    Also werde ich, dem jeweils wartenden CPU-Kern die nächste Zahl zum berechnen geben? So habe ich dies verstanden. Dafür muss man ja ermitteln welcher Kern gerade frei ist, hmmhmmmmm "nächste Frage"?

    Für die, die es interessiert. Hier ist mein SingleCoreCode....nicht anspruchsvoll
    aber leicht erweiterbar.

    // PrimSingleCore.cpp : Definiert den Einsprungpunkt für die Anwendung.
    //
    
    #include "stdafx.h"
    #include <windows.h>
    #include <stdlib.h>
    #include <math.h>
    
    LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
    
    HINSTANCE hInstGlobal;
    HWND hWindow, hButtonStart, hButtonStop, hButtonExit;
    HDC hdc;
    static RECT rect, rect1;
    SYSTEMTIME systime,systimeold;			//time-variable
    int hDiff = 0;
    int mDiff = 0;
    int sDiff = 0;
    int msDiff = 0;
    CONST aim = 500000;						//Zielzahl
    int count;								//Anzahl
    char *Gstring;							//globaler String
    bool th1runs;
    bool flag1;
    const UINT TimerSec = 1;				//TIMER
    
    int APIENTRY WinMain(HINSTANCE hInstance,
    					 HINSTANCE hPrevInstance,
    					 LPSTR lpCmdLine,
    					 int nCmdShow )
    {
    	hInstGlobal = hInstance;
    	WNDCLASS WndClass;
    	WndClass.style = 0;
    	WndClass.cbClsExtra = 0;
    	WndClass.cbWndExtra = 0;
    	WndClass.lpfnWndProc = WndProc;
    	WndClass.hInstance = hInstance;
    	WndClass.hbrBackground = (HBRUSH) (COLOR_WINDOW+11);
    	WndClass.hCursor = LoadCursor (NULL, IDC_ARROW);
    	WndClass.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    	WndClass.lpszMenuName = 0;
    	WndClass.lpszClassName = "WinProg";
    
    	RegisterClass(&WndClass);
    
    		Gstring = new char[20];
    		SetTimer(hWindow, TimerSec, 14, NULL);				//TIMER
    
    	hWindow = CreateWindow("WinProg","PrimDualCore",
    							WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX,
    							0,0,800,600,NULL,NULL,
    							hInstance, NULL);
    
    	ShowWindow (hWindow, nCmdShow);
    	UpdateWindow (hWindow);
    	MSG Message;
    	while (GetMessage(&Message, NULL, 0, 0))
    	{
    		DispatchMessage(&Message);
    	}
    	return (Message.wParam);
    }
    
    void calcDiff()		//Zeitschieber-Methode
    	{
    		hDiff = systime.wHour-systimeold.wHour;
    		mDiff = systime.wMinute-systimeold.wMinute;
    		sDiff = systime.wSecond-systimeold.wSecond;
    		msDiff= systime.wMilliseconds-systimeold.wMilliseconds;
    
    		if(msDiff<0){sDiff--; msDiff=msDiff+1000;}
    		if(sDiff<0){mDiff--; sDiff=sDiff+60;}
    		if(mDiff<0){hDiff--; mDiff=mDiff+60;}
    		if(hDiff<0){hDiff=hDiff+24;}
    	}
    
    bool Prim(int zahl)
    {
    	bool devided = false;
    //	erg = sqrt(aim);
    
    	for(int k=3;k<(sqrt(zahl)+1);k=k+2)
    	{
    		if((zahl%k) == 0){ devided=true; k=zahl;}
    	}
    
    	return !devided;
    }
    
    DWORD WINAPI ThreadProc1( LPVOID pvoid )
    {
    	flag1 = false;
    	InvalidateRect(hWindow, &rect1, TRUE);
    	TEXTMETRIC tm;
    	GetTextMetrics (hdc, &tm);
    	int i;		//Laufvariable
    	int ix,iy;
    	count=1;	//wegen der 2
    	ix = 0;
    	iy = 0;
    	char *string;
    	string = new char[20];
    
    	{							// einmalige Ausgabe der 2 da diese nicht im DB von Prim(2) ist
    		hdc = GetDC (hWindow);
    		SetBkColor (hdc, RGB(236,233,216));
    		wsprintf(string,"%01d",2);
    		TextOut (hdc, ix, iy, string, lstrlen(string));
    		iy = iy + tm.tmHeight;
    		ReleaseDC (hWindow, hdc);
    	}
    
    		for (i=3;i<=aim;i=i+2)
    		{
    			if(Prim(i))
    			{
    				count++;
    				hdc = GetDC (hWindow);
    				wsprintf(string,"%01d",i);
    				SetBkColor (hdc, RGB(236,233,216));
    				TextOut (hdc, ix, iy, string, lstrlen(string));
    				iy = iy + tm.tmHeight;
    
    				if ((iy/tm.tmHeight) == 33)
    				{
    					iy = 0;
    					ix = ix + 90;
    				}
    				if(ix>770) { ix=0; iy=0;}
    				ReleaseDC (hWindow, hdc);
    			}
    		}
    
    	flag1 = true;
    	GetSystemTime(&systime);		//take time END
    	calcDiff();
    	InvalidateRect(hWindow, &rect1, TRUE);
    
    	delete [] string;
    	th1runs = false;
    	return NULL;
    }
    
    LRESULT CALLBACK WndProc (HWND hWnd, UINT uiMessage,
    						  WPARAM wParam,LPARAM lParam)
    {
    	static HANDLE hThread1;
    	switch(uiMessage)
    	{
    		case WM_SIZE:
    		{
    			rect.left = 0;			//x-links	TEST
    			rect.top = 0;			//y-oben	TEST
    			rect.right = 800;		//x-rechts	TEST
    			rect.bottom = 600;		//y-unten	TEST
    
    			rect1.left = 360;		//x-links	TEST
    			rect1.top = 530;		//y-oben	TEST
    			rect1.right = 800;		//x-rechts	TEST
    			rect1.bottom = 600;		//y-unten	TEST
    			return 0;
    		}
    
    		case WM_CREATE:
    			hButtonStart = CreateWindow	("BUTTON","START",
    										 WS_CHILD | WS_VISIBLE |
    										 BS_PUSHBUTTON,
    										 10,540,100,20,
    										 hWnd,(HMENU) 1,
    										 hInstGlobal, NULL);
    
    			hButtonStop = CreateWindow ("BUTTON","STOP",
    										 WS_CHILD | WS_VISIBLE |
    										 BS_PUSHBUTTON,
    										 120,540,100,20,
    										 hWnd,(HMENU) 2,
    										 hInstGlobal, NULL);
    
    			hButtonExit = CreateWindow("BUTTON","Exit",
    										WS_CHILD | WS_VISIBLE |
    										BS_PUSHBUTTON,
    										250,540,80,20,
    										hWnd,(HMENU) 3,
    										hInstGlobal, NULL);
    			return 0;
    
    		case WM_TIMER:
    		{
    			//InvalidateRect(hWnd, &rect1, TRUE);	// bewirkt die Aktuallisierung im Bereich von rect1				//TIMER
    			return 0;
    		}
    
    		case WM_PAINT:
    		{
    			HDC hdc;
     			PAINTSTRUCT ps;
    			char *WMstring;
    			WMstring = new char[1];
    			WMstring[0] = 169;			// das (C)reated	
    
    			hdc = BeginPaint (hWnd, &ps);							//BEGIN PAINT
    				SetBkColor (hdc, RGB(236,233,216));
    				SetTextColor (hdc, RGB(180,0,0));
    				TextOut (hdc, 360, 540, "time: ", lstrlen("time: "));
    				if(flag1)
    				{
    					wsprintf( Gstring , "%02d:%02d:%02d:%03d",hDiff,mDiff,sDiff,msDiff);
    					TextOut (hdc, 400, 540, Gstring, lstrlen(Gstring));
    				}
    				SetTextColor (hdc, RGB(0,180,0));
    				TextOut (hdc, 540, 540, "count: ", lstrlen("count: "));
    				if(flag1)
    				{
    					wsprintf( Gstring , "%01d",count);
    					TextOut (hdc, 590, 540, Gstring, lstrlen(Gstring));
    				}
    
    			SetTextColor (hdc, RGB(187,187,187));
    			SetBkColor (hdc, RGB(236,233,216));			//Rot=236 Grün=233 Blau=216 (standart Hellgrau)
    			TextOut (hdc, 520+184,540, WMstring, 1);
    			TextOut (hdc, 520+200,540, "by rom4o", 8);
    			EndPaint (hWnd, &ps);									//END PAINT
    			delete WMstring;
    			return 0;
    		}
    
    		case WM_COMMAND:
    			if (HIWORD(wParam) == BN_CLICKED)
    			{
    				if ( (LOWORD(wParam) == 1) && (th1runs == false) )
    				{
    					hdc = GetDC (GetParent((HWND) lParam));
    					InvalidateRect(hWnd, &rect, TRUE);
    					DWORD dwThreadParam1 = 1;
    					DWORD dwThreadID1;
    
    					th1runs = true;
    					GetSystemTime(&systimeold);		//take time BEGIN
    					hThread1 = CreateThread (NULL, 0, ThreadProc1,
    											&dwThreadParam1, 0, &dwThreadID1);
    
    				}
    
    				if (LOWORD(wParam) == 2)
    				{
    					TerminateThread (hThread1, 0);
    					th1runs = false;
    				}
    
    				if (LOWORD(wParam) == 3)
    				{
    					SendMessage (GetParent((HWND)lParam), WM_DESTROY ,0 ,0);
    				}
    			}
    			return 0;
    
    		case WM_DESTROY:
    			PostQuitMessage(0);
    			return 0;
    
    		default:
    			return DefWindowProc (hWnd, uiMessage, wParam, lParam);
    	}
    

    Nun denn vielen Dank für den Tip, ich grüble weiter und gehen nun erstmal zu Bett.

    grüße rom40


Anmelden zum Antworten