www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - each! vs foreach parallel timings

reply Jay Norwood <jayn prismnet.com> writes:
I'm doing some re-writing and measuring.  The basic task is to 
take 10K samples (in struct S samples below) and calculate some 
metrics (just per sample for now).  It isn't evident to me how to 
write the parallel foreach in the same format as each!, so I just 
used the loop form that I understood.

Measured times below are for processing three simple metrics 100 
times on 10K samples. This parallel mode could be very useful in 
my work, which involves processing a bunch of hardware 
performance data.


This is on windows, corei5, DMD32 D Compiler v2.069.2, debug 
build.

each! time:59 ms
parallel! time:20 ms

import std.stdio;
import std.algorithm;
import std.conv;
import std.range;
import std.typecons;
import std.parallelism;
import std.array;
import std.traits;
import std.datetime;

struct S { int sn; ulong a; ulong b; ulong c; ulong d; double e; 
ulong f; ulong m1; double m2; double m3;}

void apply_metrics(int i,ref S s){
	with(s){
		m1 = a+b;
		m2 = (c+d)/e;
		m3 = (c+f)/e;
		sn = i;
	}
}

int main()
{

	S[10000] samples;
	// initialize some values
	foreach ( int i, ref s; samples){
		int j=i+1;
		with (s){
			a=j; b=j*2; c=j*3; d=j*4; e=j*10; f=j*5;
		}
	}

	auto sw = StopWatch(AutoStart.yes);
	// apply several functions on each  sample, also number the 
samples
	foreach(j;iota(100))
	samples[].each!((int i, ref a)=>apply_metrics(i,a));
	writeln("each! time:", sw.peek().msecs, " ms");

	auto sw2 = StopWatch(AutoStart.yes);
	// do the same as above, but in parallel
	foreach(j;iota(100))
		foreach( i, ref a; parallel(samples[])){ apply_metrics(i,a);}
	writeln("parallel! time:", sw2.peek().msecs, " ms");
	return 0;
}
Dec 27 2015
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 12/27/2015 11:30 AM, Jay Norwood wrote:

      samples[].each!((int i, ref a)=>apply_metrics(i,a));
Are you using an older compiler? That tuple expansion does not work any more at least with dmd v2.069.0 but you can use enumerate(): samples[].enumerate.each!(t=>apply_metrics(t[0].to!int,t[1]));
          foreach( i, ref a; parallel(samples[])){ apply_metrics(i,a);}
That does not compile because i is size_t but apply_metrics() takes an int. One solution is to call to!int: foreach( i, ref a; parallel(samples[])){ apply_metrics(i.to!int,a);} To not answer your actual question, I don't think it's possible. :) Ali
Dec 27 2015
parent reply Jay Norwood <jayn prismnet.com> writes:
On Sunday, 27 December 2015 at 23:42:57 UTC, Ali Çehreli wrote:
 On 12/27/2015 11:30 AM, Jay Norwood wrote:

      samples[].each!((int i, ref a)=>apply_metrics(i,a));
Are you using an older compiler? That tuple expansion does not work any more at least with dmd v2.069.0 but you can use enumerate(): samples[].enumerate.each!(t=>apply_metrics(t[0].to!int,t[1]));
          foreach( i, ref a; parallel(samples[])){
apply_metrics(i,a);} That does not compile because i is size_t but apply_metrics() takes an int. One solution is to call to!int: foreach( i, ref a; parallel(samples[])){ apply_metrics(i.to!int,a);} To not answer your actual question, I don't think it's possible. :) Ali
The code I posted was compiled with v2.069.2. It isn't creating a tuple return value in this code. I'll re-check it.
Dec 27 2015
parent reply Jay Norwood <jayn prismnet.com> writes:
 On Sunday, 27 December 2015 at 23:42:57 UTC, Ali Çehreli wrote:
 That does not compile because i is size_t but apply_metrics() 
 takes an int. One solution is to call to!int:

         foreach( i, ref a; parallel(samples[])){ 
 apply_metrics(i.to!int,a);}
It builds for me still, and executes ok, but must be because size_t and i are both 32 bits on Win32 build.
Dec 27 2015
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 12/27/2015 04:17 PM, Jay Norwood wrote:
 On Sunday, 27 December 2015 at 23:42:57 UTC, Ali Çehreli wrote:
 That does not compile because i is size_t but apply_metrics() takes
 an int. One solution is to call to!int:

         foreach( i, ref a; parallel(samples[])){
 apply_metrics(i.to!int,a);}
It builds for me still, and executes ok, but must be because size_t and i are both 32 bits on Win32 build.
Makes sense. I would still prefer size_t and even leave it out for the lambda: void apply_metrics(size_t i,ref S s){ // ... sn = i.to!int; // ... samples[].each!((i, ref a)=>apply_metrics(i,a)); Ali
Dec 27 2015