Prepare the subroutine to be run in a thread,
public class data { public int a,b; public double sum;} public static void harm(object obj){ var arg = (data)obj; arg.sum=0; for(int i=arg.a;i<arg.b;i++)arg.sum+=1.0/i; }
Create a Main function that reads—from the command-line—two parameters, the number of threads to be created and the number of terms in the harmonic sum to calculate,
int nthreads = 1, nterms = (int)1e8; /* default values */ foreach(var arg in args) { var words = arg.Split(':'); if(words[0]=="-threads") nthreads=int.Parse(words[1]); if(words[0]=="-terms" ) nterms =(int)float.Parse(words[1]); }
Prepare data-objects to be used locally in separate threads,
data[] params = new data[nthreads]; for(int i=0;i<nthreads;i++) { params[i] = new data(); params[i].a = 1 + nterms/nthreads*i; params[i].b = 1 + nterms/nthreads*(i+1); } params[params.Length-1].b=nterms+1; /* the enpoint might need adjustment */
Prepare the threads and run them, hopefully in parallel (if there is enough processors in your box),
var threads = new System.Threading.Thread[nthreads]; for(int i=0;i<nthreads;i++) { threads[i] = new System.Threading.Thread(harm); /* create a thread */ threads[i].Start(params[i]); /* run it with params[i] as argument to "harm" */ }
Join the threads,
foreach(var thread in threads) thread.Join();
Calculate the total sum,
double total=0; foreach(var p in params) total+=p.sum;
Using the POSIX "time"-utility measure the processor times running your Main with different number of threads. Something like
N=1e8 TIME = time --portability --append --output $@ Out.txt : main.exe Makefile >$@ $(TIME) mono $< -terms:$N -threads:1 >>$@ $(TIME) mono $< -terms:$N -threads:2 >>$@ $(TIME) mono $< -terms:$N -threads:3 >>$@ $(TIME) mono $< -terms:$N -threads:4 >>$@
Parallel.For
",
double sum=0; System.Threading.Tasks.Parallel.For( 1, N+1, (int i) => sum+=1.0/i );Time it and explain why it runs slower than the serial for-loop (even with one thread) and why it returns the wrong (and somewhat random) result.
using System.Linq; ... var sum = new System.Threading.ThreadLocal<double>( ()=>0, trackAllValues:true); System.Threading.Tasks.Parallel.For( 1, N+1, (int i)=>sum.Value+=1.0/i ); double totalsum=sum.Values.Sum();Does it return the correct result? Is it still slower? Why?