Download presentation
Presentation is loading. Please wait.
1
CS 284a, 14 October 1997 Copyright (c) 1997-98, John Thornley1 CS 284a Lecture Tuesday, 14 October, 1997
2
CS 284a, 14 October 1997 Copyright (c) 1997-98, John Thornley2 Structured Multithreaded Programming Systems-oriented thread libraries too complex and unstructured for high-performance multithreading. Equivalent to multithreaded goto statement. Our approach: multithreaded control structures based on familiar sequential constructs. Multithreaded program is sequential program with pragmas (that do not change sequential meaning). Most design, development, testing, and debugging is done in context of sequential interpretation.
3
CS 284a, 14 October 1997 Copyright (c) 1997-98, John Thornley3 Trivial Example: Independent Iterations int array_sum(float A[N][N]) // Sums the elements of a 2-dimensional array. { float sum, row_sum[N]; int i; sum = 0; #pragma multithreadable for (i = 0; i < N; i++) { int j; row_sum[i] = 0; for (j = 0; j < N; j++) row_sum[i] = row_sum[i] + A[i][j]; } for (i = 0; i < N; i++) sum = sum + row_sum[i]; return sum; } iterations can be executed as separate threads important that j is local!
4
CS 284a, 14 October 1997 Copyright (c) 1997-98, John Thornley4 Incorrect Example: Interfering Iterations int array_sum(float A[N][N]) // Sums the elements of a 2-dimensional array. { float sum, row_sum[N]; int i; sum = 0; #pragma multithreadable for (i = 0; i < N; i++) { int j; row_sum[i] = 0; for (j = 0; j < N; j++) row_sum[i] = row_sum[i] + A[i][j]; sum = sum + row_sum[i]; } return sum; } iterations cannot be executed as separate threads because of interference written by all iterations
5
CS 284a, 14 October 1997 Copyright (c) 1997-98, John Thornley5 Incorrect Example: Nondeterminacy int array_sum(float A[N][N]) // Sums the elements of a 2-dimensional array. { float sum, row_sum[N]; int i; lock sum_lock; lock_initialize(&sum_lock); sum = 0; #pragma multithreadable for (i = 0; i < N; i++) { int j; row_sum[i] = 0; for (j = 0; j < N; j++) row_sum[i] = row_sum[i] + A[i][j]; lock_acquire(&sum_lock); sum = sum + row_sum[i]; lock_release(&sum_lock); } lock_finalize(&sum_lock); return sum; } iterations cannot be executed as separate threads because of nondeterminacy executed in nondeterministic order
6
CS 284a, 14 October 1997 Copyright (c) 1997-98, John Thornley6 Example: Determinacy Using Counters int array_sum(float A[N][N]) // Sums the elements of a 2-dimensional array. { float sum, row_sum[N]; int i; counter sum_count; counter_initialize(&sum_count); sum = 0; #pragma multithreadable for (i = 0; i < N; i++) { int j; row_sum[i] = 0; for (j = 0; j < N; j++) row_sum[i] = row_sum[i] + A[i][j]; counter_check(&sum_count, i); sum = sum + row_sum[i]; counter_increment(&sum_count, 1); } counter_finalize(&sum_count); return sum; } iterations can be executed as separate threads executed in deterministic order
7
CS 284a, 14 October 1997 Copyright (c) 1997-98, John Thornley7 Overview of Our Structured Multithreaded Programming Model Multithreadable block and for loop pragma. Arguments to control granularity. Flags and counters for deterministic synchronization. Explicitly multithreaded block and for loop. Locks for nondeterministic synchronization. Barriers for efficiency. Library for now, transformation tool later.
8
CS 284a, 14 October 1997 Copyright (c) 1997-98, John Thornley8 What is Sthreads? Sthreads = Structured Threads. Library that supports our structured multithreaded programming model. Defined as ANSI C header file (sthreads.h). Implemented as thin layer on top of Win32 threads. Portable: other implementations to follow.
9
CS 284a, 14 October 1997 Copyright (c) 1997-98, John Thornley9 This is Sthreads! Thread Management: sthread_block(), sthread_regular_for_loop(), sthread_nested_regular_for_loop(), sthread_general_for_loop() Priorities: sthread_get_current_priority(), sthread_set_current_priority() Barriers: sthread_barrier_initialize(), sthread_barrier_finalize(), sthread_barrier_pass(), sthread_barrier_reset() Locks: sthread_lock_initialize(), sthread_lock_finalize(), sthread_lock_acquire(), sthread_lock_release() Flags: sthread_flag_initialize(), sthread_flag_finalize(), sthread_flag_set(), sthread_flag_check(), sthread_flag_reset() Counters: sthread_counter_initialize(), sthread_counter_finalize(), sthread_counter_increment(), sthread_counter_check(), sthread_counter_reset()
10
CS 284a, 14 October 1997 Copyright (c) 1997-98, John Thornley10 Multithreadable Block (Pragma) #pragma multithreadable [mapping(m)] [num_threads(t)] [priority(p)] [stack_size(s)] { statement 0 statement 1... } m =mapping of statements onto threads (simple, dynamic, blocked, or interleaved) (default = simple). t =number of threads (default = number of statements). p =initial priority of threads (default = current priority of parent thread). s =stack size of threads (in bytes) (default = system-defined constant). optional arguments
11
CS 284a, 14 October 1997 Copyright (c) 1997-98, John Thornley11 Multithreaded Block (Sthreads) int sthread_block( int num_statements, void (*statement[])(void *args), void *args, int mapping, int num_threads, int priority, unsigned int stack_size); num_statements:number of statements in the block. statement:array of pointers to functions representing statements. args:pointer to argument block passed to each statement call. mapping:mapping of statements onto threads. num_threads:number of threads. priority:priority of threads. stack_size:stack size of threads (in bytes).
12
CS 284a, 14 October 1997 Copyright (c) 1997-98, John Thornley12 A Simple Example: Array Summation int array_sum(int n, int data[]) { int i, j; int mid; int low_sum, high_sum; mid = n/2; low_sum = 0; high_sum = 0; #pragma multithreadable { for (i = 0; i < mid; i++) low_sum = low_sum + data[i]; for (j = mid; j < n; j++) high_sum = high_sum + data[j]; } return low_sum + high_sum; } separate loop control variables statement 0 statement 1 Constant variables: n, data, mid Modified variables: i, j, low_sum, high_sum
13
CS 284a, 14 October 1997 Copyright (c) 1997-98, John Thornley13 Transformation: Pragma to Sthreads Define an “argument block” structure type: –One component for each constant variable. –One pointer component for each modified variable. Declare a function for each statement: –Constant variable c replaced by (args->c). –Modified variable v replaced by (*args->v). Replace multithreadable block by block containing: –Declaration and creation of argument block variable. –Declaration and creation of array of function pointers. –Call to sthread_block() function. –Call to handle any error code returned.
14
CS 284a, 14 October 1997 Copyright (c) 1997-98, John Thornley14 typedef struct { int n, *data, mid; int *i, *j, *high_sum, *low_sum; } block_args; void statement_0(block_args *args) { for ((*args->i) = 0; (*args->i) mid); (*args->i)++) (*args->low_sum) = (*args->low_sum) + (args->data)[(*args->i)]; } void statement_1(block_args *args) { for ((*args->j) = (args->mid); (*args->j) n); (*args->j)++) (*args->high_sum) = (*args->high_sum) + (args->data)[(*args->j)]; } int array_sum(int n, int data[]) { int i, j; int mid; int low_sum, high_sum; mid = n/2; low_sum = 0; high_sum = 0; { void (*statement[2])(block_args *args); block_args args; int error_code; statement[0] = statement_0; statement[1] = statement_1; args.n = n; args.data = data; args.mid = mid; args.i = &i; args.j = &j; args.low_sum = &low_sum; args.high_sum = &high_sum; error_code = sthread_block( 2, (void (**)(void *)) statement, (void *) &args, STHREAD_MAPPING_SIMPLE, 0, STHREAD_PRIORITY_PARENT, STHREAD_STACK_SIZE_DEFAULT); handle_sthread_error(error_code); } return low_sum + high_sum; }
15
CS 284a, 14 October 1997 Copyright (c) 1997-98, John Thornley15 typedef struct { int n, *data, mid; int *high_sum, *low_sum; } block_args; void statement_0(block_args *args) { for (int i = 0; i mid; i++) *args->low_sum = *args->low_sum + args->data[i]; } void statement_1(block_args *args) { for (int j = args->mid; j n; j++) *args->high_sum = *args->high_sum + args->data[j]; } int array_sum(int n, int data[]) { int mid; int low_sum, high_sum; void (*statement[2])(block_args *args); block_args args; int error_code; mid = n/2; low_sum = 0; high_sum = 0; statement[0] = statement_0; statement[1] = statement_1; args.n = n; args.data = data; args.mid = mid; args.low_sum = &low_sum; args.high_sum = &high_sum; error_code = sthread_block( 2, (void (**)(void *)) statement, (void *) &args, STHREAD_MAPPING_SIMPLE, 0, STHREAD_PRIORITY_PARENT, STHREAD_STACK_SIZE_DEFAULT); handle_sthread_error(error_code); return low_sum + high_sum; } control variables moved inside loops unnecessary parentheses removed unnecessary block removed
16
CS 284a, 14 October 1997 Copyright (c) 1997-98, John Thornley16 Suggested Programming Style Keep two equivalent versions of multithreadable functions: (1) pragma version, (2) Sthreads version. Comment out one version at all times using /* */. Develop, test, and debug pragma version. Maintain strict equivalence of the two versions. Compile and run Sthreads version for performance. Wait patiently for automatic transformation tool.
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.