# DualCore - Prozess einem Kern zuweisen



## aniram (21. Mai 2007)

Hallo, 
ich brauch dringend und v.a.*schnell* eure Hilfe.

Ich habe ein Programm mit mehrere Threads. Jetzt möchte ich das Programm auf nur einem Kern (haben den Core2Duo) laufen lassen. 

Ich habe schon viel gegooglet, bin doch nicht richtig fündig geworden.  

Soviel wie ich weiß, sollte das mit der Funktion 
	
	
	



```
sched_setaffinity()
```
 gehen. 

Hat hier jemand mal ein Codebeispiel, wie ich den Kern1 oder Kern2 zuweisen kann?

Danke für eure Hilfe!


----------



## RedWing (21. Mai 2007)

Hallo,

ich hab zwar keinen Multicore hier und kann deswegen auch kein konkretes Beispiel geben, aber hast du schonmal ein wenig mit sched_setaffinity rumprobiert?

Also laut man Page würd ichs mal mit folgendem versuchen:


```
cpu_set_t set;
CPU_ZERO(&set);
CPU_SET(0, &set);
if (sched_setaffinity(0, sizeof(cpu_set_t), &set) < 0)
  perror("Error in sched_setaffinity()");
```

Gruß,
RedWing


----------



## aniram (21. Mai 2007)

Hi, 
das Beispiel geht leider nicht ganz. 

Brauch ich noch eine Bibliothek dazu? Habe leider mit sched_setaffinity noch nicht viel gemacht. Brauche das für eine Seminararbeit

Habe das noch gefunden. Jedoch werde ich nicht ganz schlau darauf

```
int sched_setaffinity(pid_t pid, unsigned int cpusetsize,
                      cpu_set_t *mask);

int sched_getaffinity(pid_t pid, unsigned int cpusetsize,
                      cpu_set_t *mask);

void CPU_CLR(int cpu, cpu_set_t *set);

int CPU_ISSET(int cpu, cpu_set_t *set);

void CPU_SET(int cpu, cpu_set_t *set);

void CPU_ZERO(cpu_set_t *set);
```


----------



## RedWing (21. Mai 2007)

aniram hat gesagt.:


> Hi,
> das Beispiel geht leider nicht ganz.
> 
> Brauch ich noch eine Bibliothek dazu?


Was geht denn nicht bzw was ist der Fehler? Gibt es Linker Probleme? Wenn ja wie schauen die aus? Bei funktionalen Fehlern kann ich dir leider auch nich helfen da ich hier kein Multicore hab und meine Hypothesen so nicht testen kann 



aniram hat gesagt.:


> Habe das noch gefunden. Jedoch werde ich nicht ganz schlau darauf
> 
> ```
> int sched_setaffinity(pid_t pid, unsigned int cpusetsize,
> ...



Das ist doch genau das was ich im Bsp. auch verwende:
Das Prinzip der API funktioniert ähnlich denke ich mal wie bei der von select:
Du hast ein Feld vom Typ cpu_set_t wo jedes einzelne Element in diesem Feld die jeweilige CPU repräsentiert. CPU_ZERO initialisiert dieses Feld mit 0en. CPU_SET enabled eine bestimmte CPU mit dem jeweiligen Index "cpu" und CPU_CLEAR disabled die jeweilige CPU mit dem Index 'cpu', so entnehm ich das zumindest der man Page:

http://www.die.net/doc/linux/man/man2/sched_setaffinity.2.html

Gruß,
RedWing


----------



## RedWing (21. Mai 2007)

Du kannst ja auch mal zu Testzwecken von deinem Programm, was ich nehme mal an momentan von 2 Cores bedient wird, die affinity mit getaffinity auslesen und dann mit CPU_ISSET überprüfen welche Bits in dem Feld gesetzt sind was du zurückbekommst und schauen ob es deinen Erwartungen entspricht.

Gruß,
RedWing


----------



## aniram (21. Mai 2007)

Habs jez so probiert

```
int mask = 0xFFFFFFFF;

int sched_setaffinity(pid_t pid, unsigned int cpusetsize,
                      cpu_set_t *mask);
```

_0xFFFFFFFF 
is all processors (#0 through #31)_

_0x00000001 
is processor #0_

Müsste doch so stimmen, oder?


----------



## RedWing (21. Mai 2007)

aniram hat gesagt.:


> Habs jez so probiert
> 
> ```
> int mask = 0xFFFFFFFF;
> ...



Ich glaube die haben die Makros CPU_SET, CPU_CLEAR, CPU_ZERO, etc nicht umsonst definiert 
Du solltest diese und insbesondere auch den Datentyp cpu_set_t verwenden, ansonsten ist die Wahrsch. noch geringer das es funktioniert 

Gruß,
RedWing


----------



## aniram (21. Mai 2007)

Hmm...Wie würdest du das machen? Ich habe solangsam keinen Nerv mehr und brauche das bis morgen


----------



## aniram (21. Mai 2007)

RedWing hat gesagt.:


> Was geht denn nicht bzw was ist der Fehler? Gibt es Linker Probleme? Wenn ja wie schauen die aus? Bei funktionalen Fehlern kann ich dir leider auch nich helfen da ich hier kein Multicore hab und meine Hypothesen so nicht testen kann



_cpu_2.c:13: error: expected declaration specifiers or '...' before '&' token
cpu_2.c:13: warning: data definition has no type or storage class
cpu_2.c:14: error: expected declaration specifiers or '...' before numeric constant
cpu_2.c:14: error: expected declaration specifiers or '...' before '&' token
cpu_2.c:14: warning: data definition has no type or storage class
cpu_2.c:15: error: expected identifier or '(' before 'if'_

L= line

```
L13:CPU_ZERO(&set);
L14: CPU_SET(0, &set);
L15:if (sched_setaffinity(0, sizeof(cpu_set_t), &set) < 0)
```


----------



## RedWing (21. Mai 2007)

Hast du sched.h denn inkludiert?

Gruß,
RedWing


----------



## aniram (21. Mai 2007)

ja, hab ich ....


----------



## RedWing (21. Mai 2007)

Probiers mal so:

```
#include <errno.h>
#define __USE_GNU
#include <sched.h>
#undef __USE_GNU

int
main (void)
{
    cpu_set_t set;
    CPU_ZERO(&set);
    CPU_SET(0, &set);
    if (sched_setaffinity(0, sizeof(cpu_set_t), &set) < 0)
        perror("Error in sched_setaffinity()");
    return 0;
}
```

Gruß,
RedWing


----------



## aniram (21. Mai 2007)

sollte klappen, 

_cpu_1.c:62: error: redefinition of ‘main’
cpu_1.c:10: error: previous definition of ‘main’ was here
_
jedoch habe ich shcon ne main-funktion


----------



## aniram (21. Mai 2007)

Hier mal der ganze Code:

```
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

volatile int x = 0, y = 0;/* 'volatile' is important! */


pthread_mutex_t x_mutex, y_mutex;


#define ITERATIONS 5000000
/* good value for Athlon 900, eventually adjust for faster/slower processors */
void *thread_routine_0 (void *data) 
{
	int n;
	
	for (n = 0; n < ITERATIONS; n++) {
		pthread_mutex_lock (&x_mutex);
		pthread_mutex_lock (&y_mutex);
		
		x++;
    		y += 2;
		
		pthread_mutex_unlock (&x_mutex);
		pthread_mutex_unlock (&y_mutex);
		}
	return NULL; /* we do not want to return any data */
}

void *thread_routine_1 (void *data)
{
	int n;
	
	for (n = 0; n < ITERATIONS; n++) {
		pthread_mutex_lock (&x_mutex);
		pthread_mutex_lock (&y_mutex);
		
		x++;
    		y += 2;
		
		pthread_mutex_unlock (&x_mutex);
		pthread_mutex_unlock (&y_mutex);
		}
	return NULL; /* we do not want to return any data */
}

int main () {
	pthread_t threads[2];
	int n;
	/* Init mutexes... */
	pthread_mutex_init (&x_mutex, NULL); /* 'NULL' = options (defaults are ok) */
	pthread_mutex_init (&y_mutex, NULL); /* 'NULL' = options (defaults are ok) */
	/* Create threads */
	if (pthread_create (&threads[0], NULL, thread_routine_0, NULL) != 0) 
	{
		puts ("Error creating thread #0!");
		exit (3);
	}
	if (pthread_create (&threads[1], NULL, thread_routine_1, NULL) != 0) 
	{
		puts ("Error creating thread #1!");
		exit (3);
	}
	/* Join the threads (wait until they finished) */
	for (n = 0; n < 2; n++)
		pthread_join (threads[n], NULL);
		/* Cleanup mutexes... */
		pthread_mutex_destroy (&x_mutex);
		pthread_mutex_destroy (&y_mutex);
		/* Print the final values of x and y */
		printf ("x = %i, y = %i\n", x, y);
	return 0;
}
```


----------



## RedWing (21. Mai 2007)

Dann entferne die main Signatur doch und setz den Programmcode am Anfang von DEINER main- Funktion ein. Ein bisschen selber denken hat noch niemanden geschadet ... Entschuldige die blöde Bemerkung 
Mich würde intressieren ob das dann so geklappt hat, also halt mich auf dem Laufenden.

Gruß,
RedWing


----------



## aniram (21. Mai 2007)

Ging nicht....

_cpu_1.c:51: undefined reference to `CPU_ZERO'
cpu_1.c:52: undefined reference to `CPU_SET'
_

Ich bin jetzt aber andersweitig noch fündig geworden.
http://www.die.net/doc/linux/man/man1/taskset.1.html

Damit geht es, nur habe ich da ein "komisches" Ergebnis festgestellt.
Das Programm lauft auf 2 Kernen doppelt so langsam 
Liegt das an der Synchronisation und Overhead, oder wie ist sich das zu erklären?


----------



## RedWing (21. Mai 2007)

aniram hat gesagt.:


> Ging nicht....
> 
> _cpu_1.c:51: undefined reference to `CPU_ZERO'
> cpu_1.c:52: undefined reference to `CPU_SET'
> ...


wichtig ist das du sched.h so inkludierst:

```
#define __USE_GNU
#include <sched.h>
#undef __USE_GNU
```
da hat das Programm bei mir zumindest kompiliert und auch gelinkt ...



aniram hat gesagt.:


> Damit geht es, nur habe ich da ein "komisches" Ergebnis festgestellt.
> Das Programm lauft auf 2 Kernen doppelt so langsam
> Liegt das an der Synchronisation und Overhead, oder wie ist sich das zu erklären?



Ja ich denke das liegt an der Synchronisation. AFAIK wird ein Programm auf "per Thread" Basis auf beide CPUs vom Kernel verteilt. Deine Synchronisation hat nun folgende Nachteile:
1.) Macht sie die durch den Multicore gewonne echte Parallelität kaputt
2.) Muss Interprozessorkommunikation über einen globalen Speicher (wegen deines Mutex) betrieben werden.

Wieso das das Programm aber gleich DOPPELT so langsam macht, da ja insbesondere auch Punkt 1 im Gegensatz zur Unicoreversion keinen großen Nachteil bringt,  weiß ich auch nicht, (evtl. ja (Achtung Mutmaßung ) wegen Ausnutzung von Hypethreading bei Unicorebetrieb).

Gruß,
RedWing


----------



## aniram (22. Mai 2007)

Wie könnt ich denn den Code optimieren, dass er auf 2 Kernen schneller läuft?
Oder gibt es hier im Forum Beispiel-Code, die auf DualCores schneller laufen?

Wie funktioniert Multi-Core Programmierung?


----------



## RedWing (22. Mai 2007)

Hallo,



> Wie könnt ich denn den Code optimieren, dass er auf 2 Kernen schneller läuft?



Dafür gibt es denke kein Patentrezept. Besonders bei deinem Code sieht die Sache kritisch aus, da jeweils beide Threads schreibend auf die Variable zugreifen und somit Synchronisation unumgänglich ist. Es sei denn du willst bewußt nichtdeterministische Raceconditions hervorufen .
Anders sieht die Situation aus wenn du einen Leser und einen Schreiber hast. Da gibt es mehrere Ansätze die je nach Anwendung mehr oder weniger gut passen und die versuchen das Optimum an Parallelität rauszuholen. Stichworte dafür wären:
die Verwendung eines Wechselpuffers, eines Ringpuffers, oder des Frame-Counter Protokolls.


> Wie funktioniert Multi-Core Programmierung?



Da kann ich dich leider auch nur in Richtung google verweisen ...

Gruß,
RedWing


----------



## aniram (22. Mai 2007)

Hi, 
ich habe jetzt vom Prof. ein weiteres Beispiel bekommen. Dort funktioniert es. Ich habe ein Array und berechne die obere und untere Hälfte in jeweils zwei Threads. Hier ist das Progamm ca 1,9x so schnell 

Das ganze wollt ich jetzt mit 3 Threads realisieren und zu sehen, wie sich das auf 2 Kerne ausmacht. Verhältnis wäre ja 2:1 oder 1:2 ...

Allerdings läuft es trotzdem doppelt so schnell, was ja normal nicht sein dürfte!?


----------



## RedWing (22. Mai 2007)

Hallo,


aniram hat gesagt.:


> Hi,
> ich habe jetzt vom Prof. ein weiteres Beispiel bekommen. Dort funktioniert es. Ich habe ein Array und berechne die obere und untere Hälfte in jeweils zwei Threads. Hier ist das Progamm ca 1,9x so schnell


wie sieht das Programm denn aus? Werden die zwei Hälften des Arrays unabhängig von den 2 Threads berechnet? Ich denke mal das du da ohne Synchronisation auskommst, oder? Kann man von deinem Seminar eigtl. was bestaunen(also so Folientechnisch), würde mich selbst mal intressieren ...

Gruß,
RedWing


----------



## aniram (22. Mai 2007)

Ich muss ein Referat und eine Arbeit zum Thema: "Aufgaben eines Mehrprozessorfähigen Betriebssystems" schreiben.

odd & even kannst hier ignorieren. Ist nicht so gut, wegen der Cache-Kohärenz. Lieber das Array halbieren, als gerade & ungerade berechnen.
Ich bekomm das aber mit dem dritten Thread nicht hin 


```
#include <thread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
#include <sys/errno.h>
#include <sys/processor.h>
#include <sys/procset.h>
#define CACHE_LINE_SIZE 32
#define DIV_NUMBER 114
#define CPU_ID_A 3
#define CPU_ID_B 4

static float* array1;
static float* array2;
int size;
int loop;

void *process_even(void* threadid);
void *process_odd(void* threadid);
void *process_lower(void* threadid);
void *process_upper(void* threadid);
void wrong_input(void);



int main (int argc, char *argv[])
{
	int rc, t;
	long t1,t2;
	char type;
	t1 = 0;
	t2 = 0;
	

	if(argc < 4)
		wrong_input();

	type = argv[1][0];
	size = atoi(argv[2]);
	loop = atoi(argv[3]);

	if((type != '1')&&(type != '0')||(size <= 0)||(loop <= 0)||(size%2 != 0))
		wrong_input();

	/* Speicherreservierung. valloc reserviert Speicher am Block Anfang.
	Mit dif wird der reservierte Speicher auf ein exaktes vielfaches der Cache-Line größe erweitert */

	int dif = CACHE_LINE_SIZE-( (size*sizeof(float) )%CACHE_LINE_SIZE);
	array1 = valloc(dif+size*sizeof(float));
	array2 = valloc(dif+size*sizeof(float));

	/* init array */
	int i;
	for(i = 0; i< size; i++){
		array1[i] = (float)i;
		array2[i] = (float)i;
	}
	t = 0;
	pthread_t thread_even;
	pthread_t thread_odd;
	pthread_t thread_upper;
	pthread_t thread_lower;

	t1 = clock();

	/* Berechnung EVEN / ODD */
	if(type == '1'){
		rc = pthread_create(&thread_even, NULL, process_even,(void *)t);
		if (rc){
			printf("ERROR; return code from pthread_create() is %d\n", rc);
       		exit(1);
		}

		process_odd(&t);
		rc = pthread_join(thread_even, NULL); /* Auf thread warten */
	}

	/* Berechnung UPPER / LOWER */
	else if(type == '0'){
		rc = pthread_create(&thread_upper, NULL, process_upper,(void *)t);
		if (rc){
       		printf("ERROR; return code from pthread_create() is %d\n", rc);
			exit(-1);
		}

		process_lower(&t);
		rc = pthread_join(thread_upper, NULL); /* Auf thread warten */
	}
		t2 = clock();
		if(type == '1')
			printf("\nType: Even/Odd");
		else
			printf("\nType: Upper/Lower");

		printf("\nTime: %d,  size: %d,  loop: %d\n\n", (t2-t1)/1000, size, loop);
	
	pthread_exit(NULL);
}


/* Berechnen der geraden Einträge */
void *process_even(void* threadid){
/*int ret = processor_bind(P_LWPID, P_MYID, 2, NULL);
assert(ret == 0);
printf("\nCpu_id: %d", getcpuid());*/

int i, inner_l;
for(inner_l = 0; inner_l < loop; inner_l++)
	for(i = 0; i < size; i = i+2)
		array1[i] = (array1[i] + array2[i]) / DIV_NUMBER;
}

/* Berechnen der ungeraden Einträge */
void *process_odd(void* threadid){
/*int ret = processor_bind(P_LWPID, P_MYID, 6, NULL);
assert(ret == 0);
printf("\nCpu_id: %d", getcpuid());*/

int i, inner_l;
for(inner_l = 0; inner_l < loop; inner_l++)
	for(i = 1; i < size; i = i+2)
		array1[i] = (array1[i] + array2[i]) / DIV_NUMBER;
}

/* Berechnen der ersten Hälfte der arrays */
void *process_upper(void* threadid){
/*int ret = processor_bind(P_LWPID, P_MYID, 2, NULL);
assert(ret == 0);
printf("\nCpu_id: %d", getcpuid());*/

int upper_end = (size/2) -1;

int i, inner_l;
for(inner_l = 0; inner_l < loop; inner_l++)
	for(i = 0; i < upper_end; i++)
		array1[i] = (array1[i] + array2[i]) / DIV_NUMBER;
}


/* Berechnen der zweiten Hälfte der arrays */
void *process_lower(void* threadid){
/*int ret = processor_bind(P_LWPID, P_MYID,6, NULL);
assert(ret == 0); 
printf("\nCpu_id: %d", getcpuid());*/

int lower_start = size/2;
int i, inner_l;
for(inner_l = 0; inner_l < loop; inner_l++)
	for(i = lower_start; i < size; i++)
		array1[i] = (array1[i] + array2[i]) / DIV_NUMBER;
}


void wrong_input(){
	printf("\nWrong argument count!\n");
	printf("\nArg1: type 0 = upper/lower, 1 = even/odd");
	printf("\nArg2: array size (number of floats). Size modulo 2 must be 0.");
	printf("\nArg3: loop count");
	exit(0);
}
```

Hier mein Ansatz:

```
/* Berechnen der ersten H?lfte der arrays */
void *process_upper(void* threadid){
/*int ret = processor_bind(P_LWPID, P_MYID, 2, NULL);
assert(ret == 0);
printf("\nCpu_id: %d", getcpuid());*/

int upper_end = (size/3) -1;

int i, inner_l;
for(inner_l = 0; inner_l < loop; inner_l++)
	for(i = 0; i < upper_end; i++)
		array1[i] = (array1[i] + array2[i]) / DIV_NUMBER;
}


/* Berechnen des Mittleren Arrays */
void *process_middle(void* threadid){
/*int ret = processor_bind(P_LWPID, P_MYID,6, NULL);
assert(ret == 0); 
printf("\nCpu_id: %d", getcpuid());*/

int middle_start = size/3;
int lower_end = ((size/3)*2) -1;
int i, inner_l;
for(inner_l = 0; inner_l < loop; inner_l++)
	for(i = middle_start; i < lower_end; i++)
		array1[i] = (array1[i] + array2[i]) / DIV_NUMBER;
}


/* Berechnen der dritten H?lfte der arrays */
void *process_lower(void* threadid){
/*int ret = processor_bind(P_LWPID, P_MYID,6, NULL);
assert(ret == 0); 
printf("\nCpu_id: %d", getcpuid());*/

int lower_start = (size/3)*2;
int i, inner_l;
for(inner_l = 0; inner_l < loop; inner_l++)
	for(i = lower_start; i < size; i++)
		array1[i] = (array1[i] + array2[i]) / DIV_NUMBER;
}
```


----------



## RedWing (22. Mai 2007)

Also spontan fällt mir auf das du immer ein Element auslässt...
Ich denke so ists richtig:


```
/* Berechnen der ersten H#lfte der arrays */
void *process_upper(void* threadid){
    /*int ret = processor_bind(P_LWPID, P_MYID, 2, NULL);
      assert(ret == 0);
      printf("\nCpu_id: %d", getcpuid());*/

    int upper_end = (size/3);

    int i, inner_l;
    printf("Starting at %d Ending at %d\n", 0, upper_end);
    for(inner_l = 0; inner_l < loop; inner_l++)
        for(i = 0; i < upper_end; i++)
            array1[i] = (array1[i] + array2[i]) / DIV_NUMBER;
}

/* Berechnen des Mittleren Arrays */
void *process_middle(void* threadid){
    /*int ret = processor_bind(P_LWPID, P_MYID,6, NULL);
      assert(ret == 0); 
      printf("\nCpu_id: %d", getcpuid());*/

    int middle_start = size/3;
    int lower_end = (size/3)*2;
    int i, inner_l;
    printf("Starting at %d Ending at %d\n", middle_start, lower_end);
    for(inner_l = 0; inner_l < loop; inner_l++)
        for(i = middle_start; i < lower_end; i++)
            array1[i] = (array1[i] + array2[i]) / DIV_NUMBER;
}

/* Berechnen der dritten H#lfte der arrays */
void *process_lower(void* threadid){
    /*int ret = processor_bind(P_LWPID, P_MYID,6, NULL);
      assert(ret == 0); 
      printf("\nCpu_id: %d", getcpuid());*/

    int lower_start = (size/3)*2;
    int i, inner_l;
    printf("Starting at %d Ending at %d\n", lower_start, size);
    for(inner_l = 0; inner_l < loop; inner_l++)
        for(i = lower_start; i < size; i++)
            array1[i] = (array1[i] + array2[i]) / DIV_NUMBER;
}
```

Gruß,
RedWing


----------



## aniram (22. Mai 2007)

Ich lass kein Element aus
oben: 0 bis i-1
mitte: i bis k -1
unten: k bis ende

Deine Variante läuft trotzdem 2x so schnell, genauso wie bei mir


----------



## RedWing (22. Mai 2007)

aniram hat gesagt.:


> Ich lass kein Element aus
> oben: 0 bis i-1
> mitte: i bis k -1
> unten: k bis ende


Nat. läßt du eins aus. Wenn du mir nicht glaubst schau mal auf deinen end_wert( der is nämlich jeweils i -1 bis auf den letzten Endwert size) und auf deine Schleifenbedingung (welche immer < anstatt <= ist). => du gehst nicht bis i-1 sondern bis i -2 und fängst im nächsten bei i  wieder an => du hast ein Element ausgelassen.



> Deine Variante läuft trotzdem 2x so schnell, genauso wie bei mir



Ja hab ja auch nichts sonst weiter dran geändert. 


Gruß,
RedWing


----------



## aniram (22. Mai 2007)

> Nat. läßt du eins aus. Wenn du mir nicht glaubst schau mal auf deinen end_wert( der is nämlich jeweils i -1 bis auf den letzten Endwert size) und auf deine Schleifenbedingung (welche immer < anstatt <= ist). => du gehst nicht bis i-1 sondern bis i -2 und fängst im nächsten bei i  wieder an => du hast ein Element ausgelassen.


Stimmt, verzeih mir 
Ich sitzt heut schon wieder zulange vorm Rechner ;(



> Ja hab ja auch nichts sonst weiter dran geändert.


Wo liegt dann noch der Fehler?


----------



## RedWing (22. Mai 2007)

aniram hat gesagt.:


> Stimmt, verzeih mir
> Ich sitzt heut schon wieder zulange vorm Rechner ;(


Kein Problem, kann ich verstehen 



aniram hat gesagt.:


> Wo liegt dann noch der Fehler?


Hast du denn den 3ten Thread auch gestartet? Also in deinem Code kann man davon nämlich nichts sehen.
Falls doch, weiß ichs auch nicht, dazu kenn ich die "Linux Internals" insbesondere den  Load Balancer vom Scheduler (das is der Teil des Linux Kernels der für die Aufteilung der Prozesse auf die versch. CPUs zuständig ist) zu wenig.  Aber vlt. solltest du dir das mal anschauen, wie Linux das Intern macht, das könnte auch für dein Seminar hilfreich sein. EIn Buch wo das sehr gut beschrieben ist (wenn du denn noch Zeit hast) ist das vom Robert Love (Linux Kernelhandbuch), oder du schaust mal bei google.

Gruß,
RedWing


----------



## aniram (22. Mai 2007)

RedWing hat gesagt.:


> Hast du denn den 3ten Thread auch gestartet?



Eigentlich ja... 

Inwieweit muss ich den dritten Thread bei der Berechnung mit einbauen?

```
/* Berechnung UPPER / LOWER */
	else if(type == '0'){
		rc = pthread_create(&thread_upper, NULL, process_upper,(void *)t);
		if (rc){
       		printf("ERROR; return code from pthread_create() is %d\n", rc);
			exit(-1);
		}

		process_lower(&t);
		rc = pthread_join(thread_upper, NULL); /* Auf thread warten */
	}
```


----------



## RedWing (22. Mai 2007)

Mhm also starten würdest du ihn so:

```
...
pthread thread_middle;
...
rc = pthread_create(&thread_upper, NULL, process_upper,(void *)t);
if (rc){
	printf("ERROR; return code from pthread_create() is %d\n", rc);
	exit(-1);
}

rc = pthread_create(&thread_middle, NULL, process_middle,(void *)t);
if (rc){
	printf("ERROR; return code from pthread_create() is %d\n", rc);
	exit(-1);
}
process_lower(&t);
rc = pthread_join(thread_upper, NULL); /* Auf upper thread warten */
rc = pthread_join(thread_middle, NULL); /* Auf middle thread warten (falls noch nicht fertig) */
```

Gruß,
RedWing


----------



## aniram (22. Mai 2007)

Jetzt siehts schonmal gut aus.
Die Zeiten auf 2 Kerne variieren! Das Prog läuft ca. 1,7-1,9x schneller
Wobei mir die 1,9 schon recht hoch erscheint

Auf einem Kern sind die Zeiten fast identisch


----------

