Finding the minimum value in an
array
- Problem description:
- Given an
array of
double typed
values in
x[0 .. (MAX-1)]
- Find the
minimum value
stored in the
array
x[0 .. (MAX-1)]
|
- Solution using
N
worker threads:
-
Split the
array
x[0 .. (MAX-1)]
into
N
equal
segments
- The main thread
spawns
k
worker threads and....
(see (4))
- Worker thread
k
performs:
- Finds the
minimum in
segment
k of the
array
- Save the
minimum found
in variable
Tmin[k]
|
- The main thread
waits
for all threads
to complete
- Then:
find the
overall minimum in
the Tmin[ ] outputs
|
|
Finding the minimum value in an
array
- How to
split the
array into
N
equal
segments:
-
Work load
distribution
for a specific
thread
s:
Let n = MAX/N (MAX = # array elements, N = #threads)
Thread 0: finds minimum over x[ 0] .. x[ n-1]
Thread 1: finds minimum over x[ n] .. x[2n-1]
...
Thread s: finds minimum over x[(s)n] .. x[(s+1)n-1]
...
Thread N-1: finds minimum over x[(N-1)n] .. x[MAX]
|
|
The main( )
function
- The
main( )
function in
psuedo code:
int main(int argc, char *argv[])
{
1. Prepare the input array x[MAX]
2. Create N threads with:
for (i = 0; i < N; i = i + 1)
{
id[i] = i; // Pass id to worker thread
pthread_create(&tid[i], NULL, worker, &id[i]) );
}
Thread i will saved the min of its segment in Tmin[i]
3. Wait for all threads to finish
4. Find min in Tmin[ ] array
}
|
|
How the main( )
function
generate a
sample input numbers
- (1) The
input x[MAX]
is generated
randomly:
#define MAX 100000000
double x[MAX]; // Input numbers
int main(int argc, char *argv[])
{
1. Prepare the input array x[MAX]
/* -----------------------------
Generate MAX random numbers
----------------------------- */
srandom(4444444);
for (i = 0; i < MAX; i++)
{
x[i] = random()/(double)1000;
}
}
|
|
How the main( )
function
create the
worker threads
- (2) The
worker threads
are created using
an
id
argument -
thread
i will
receive
id = i:
int main(int argc, char *argv[])
{
2. Create N threads
pthread_t tid[100]; // Thread ID of each thread (for pthread_join)
int id[100]; // id[i] = index of worker thread i
/* ----------------
Create threads
---------------- */
for (i = 0; i < N; i++)
{
id[i] = i; // Thread i will get id = i
if ( pthread_create(&tid[i], NULL, worker, &id[i]) )
{
perror("pthread_create");
exit(1);
}
}
}
|
|
How the main( )
function
wait for the
worker threads
to finish
- (3) The
main()
waits for the
worker threads to
finish with
pthread_join():
double Tmin[100]; // Tmin[i] = min found by thread i
int main(int argc, char *argv[])
{
3. Wait for all threads to finish
pthread_t tid[100]; // Thread ID of each thread (for pthread_join)
/* ---------------------------------------
Wait for all worker threads to finish
--------------------------------------- */
for (i = 0; i < N; i++)
{
pthread_join(tid[i], NULL);
}
// When thread i is finished, thread i would have
// put its min value in Tmin[i]
}
|
|
How the main( )
function
wait for the
worker threads
to finish
- (4)
Finally,
the
main()
function
computes the
overall minimum
using the
Tmin[ ] values:
double Tmin[100]; // Tmin[i] = min found by thread i
int main(int argc, char *argv[])
{
4. Find the min in the Tmin[ ] array
double my_min;
/* ---------------------------------------
Find the minimum in the Tmin[ ] array
--------------------------------------- */
my_min = Tmin[0];
for (i = 1; i < N; i++)
{
if ( Tmin[i] < my_min )
my_min = Tmin[i];
}
printf("Min = %lf\n", my_min); // Print out the min
}
|
|
The worker( )
function
- The
worker( )
has the parameter
id which
identifies the
segment that
the thread must
process:
void *worker(int *id) // *id = identifies the segment s below
{
int n, start, stop;
double my_min;
int s = *id; // *id = 0, 1, 2, ...or (N-1)
n = MAX/N;
start = s * n; // Start index
stop = ( (start+n < MAX) ? start+n : MAX ); // Stop index
Input x[ ]:
+---+---+---+-- ..... --+---+---+
| | | | | | |
+---+---+---+-- ..... --+---+---+
^ ^
| |
start = s*n (s+1)n-1
}
|
|
The worker( )
function
-
Copy the
argument
*id into
the variable
s
(more convenient):
void *worker(int *id) // *id = identifies the segment s below
{
int n, start, stop;
double my_min;
int s = *id; // s = one of: 0, 1, 2, ...or (N-1)
n = MAX/N;
start = s * n; // Start index
stop = ( (start+n < MAX) ? start+n : MAX ); // Stop index
Input x[ ]:
+---+---+---+-- ..... --+---+---+
| | | | | | |
+---+---+---+-- ..... --+---+---+
^ ^
| |
start = s*n (s+1)n-1
}
|
|
Find the
start index
for the worker( )
function
-
Find the
start index
of the segment for
thread
s:
void *worker(int *id) // *id = identifies the segment s below
{
int n, start, stop;
double my_min;
int s = *id; // s = one of: 0, 1, 2, ...or (N-1)
n = MAX/N; // n = size of 1 segment
start = s * n; // Start index
stop = ( (start+n < MAX) ? start+n : MAX ); // Stop index
Input x[ ]:
+---+---+---+-- ..... --+---+---+
| | | | | | |
+---+---+---+-- ..... --+---+---+
^ ^
| |
start = s*n (s+1)n-1
}
|
|
Find the
stop index
for the worker( )
function
-
Find the
stop index
of the segment for
thread
s:
void *worker(int *id) // *id = identifies the segment s below
{
int n, start, stop;
double my_min;
int s = *id; // s = one of: 0, 1, 2, ...or (N-1)
n = MAX/N; // n = size of 1 segment
start = s * n; // Start index
stop = ( (start+n < MAX) ? start+n : MAX ); // Stop index
Input x[ ]:
+---+---+---+-- ..... --+---+---+
| | | | | | |
+---+---+---+-- ..... --+---+---+
^ ^
| |
start = s*n (s+1)n-1
}
|
|
Find the
stop index
for the worker( )
function
-
Find the
minimum value
in the segment:
void *worker(int *id) // *id = identifies the segment s below
{
int n, start, stop;
double my_min;
int s = *id; // s = one of: 0, 1, 2, ...or (N-1)
n = MAX/N; // n = size of 1 segment
start = s * n; // Start index
stop = ( (start+n < MAX) ? start+n : MAX ); // Stop index
my_min = x[start]; // Initial value for the min
for (int i = start+1; i < stop; i++ )
if ( x[i] < my_min )
my_min = x[i];
}
|
|
Wrapping up
the worker( )
function
-
Save the
minimum value
in Tmin[s] and
exit:
void *worker(int *id) // *id = identifies the segment s below
{
int n, start, stop;
double my_min;
int s = *id; // s = one of: 0, 1, 2, ...or (N-1)
n = MAX/N; // n = size of 1 segment
start = s * n; // Start index
stop = ( (start+n < MAX) ? start+n : MAX ); // Stop index
my_min = x[start]; // Initial value for the min
for (int i = start+1; i < stop; i++ )
if ( x[i] < my_min )
my_min = x[i];
Tmin[s] = my_min; // Save result in Tmin[s]
pthread_exit(NULL); // Thread exits
}
|
|
DEMO:
demo/pthread/min-mt1.c
(use euler to
demo, use 14 threads...)
❮
❯