D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 15134 - std.parallelism taskPool.amap fails to compile with array of structs or Tuples with named members
Summary: std.parallelism taskPool.amap fails to compile with array of structs or Tuple...
Status: RESOLVED INVALID
Alias: None
Product: D
Classification: Unclassified
Component: phobos (show other issues)
Version: D2
Hardware: x86 Windows
: P1 blocker
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-10-01 18:32 UTC by Jay Norwood
Modified: 2015-10-01 19:31 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Jay Norwood 2015-10-01 18:32:48 UTC
This code result in the compile error. Commenting out the taskPool.amap line builds ok. Similar error for Tuples with named members substituted for the struct definitions of TR, TI, TO.  Some analysis was done by Ali Cehreli in this thread, which also has the Tuple implementation:
http://forum.dlang.org/post/mujsqv$tlk$1@digitalmars.com


import std.algorithm, std.parallelism, std.range;
import std.typecons;
import std.meta;
import std.stdio;

// define some input measurement sample tuples and output metric tuples
struct TR { long raw;}
struct TI {long L1I_MISS; long L1D_MISS; }
struct TO { TR L1_MISS; }

// various metric definitions
// using Tuples with defined names for each member, and use the names here in the metrics.
TR met_l1_miss ( ref TI m){ TR rv;  rv.raw = m.L1I_MISS+m.L1D_MISS; return rv; }

// a convenience to use all the metrics above as a list
alias Metrics = AliasSeq!(met_l1_miss);

void main(string[] argv)
{
	auto samples = iota(100);
	auto meas = new TI[samples.length];
	auto results = new TO[samples.length];

	// Initialize some values for the measured samples
	foreach(i, ref m; meas){
		m.L1D_MISS= 100+i; m.L1I_MISS=100-i;
	}

    ref TI getTerm(int i)
    {
        return meas[i];
    }

	// compute the metric results for the above measured sample values in parallel
	taskPool.amap!(Metrics)(std.algorithm.map!getTerm(samples),results);

	TR rv1 = met_l1_miss( meas[1]);

	writeln("measurements:", meas[1]);
	writeln("rv1:", rv1);
	writeln("results:", results[1]);

}

Severity	Code	Description	Project	File	Line
Error		Error: static assert  "Wrong buffer type."		C:\D\dmd2\src\phobos\std\parallelism.d	1668
Error		instantiated from here: amap!(MapResult!(getTerm, Result), TO[])		d:\visd\dmapbug\dmapbug\main.d	35
Comment 1 Jay Norwood 2015-10-01 19:24:07 UTC
This may be my problem.  I see this works with array of struct as inputs and a Tuple as result with named members. So this is not a blocker.  I'll need to check if there was some other problem with the original example which had named Tuple members and array of Tuple as the input.

import std.algorithm, std.parallelism, std.range;
import std.typecons;
import std.meta;
import std.stdio;

// define some input measurement sample tuples and output metric tuples

struct TI {long L1I_MISS; long L1D_MISS; long cycles; }
alias TO = Tuple!(long, "raw", double, "per_cyc");

// various metric definitions
// using Tuples with defined names for each member, and use the names here in the metrics.
TO met_l1_miss ( ref TI m){ TO rv;  rv.raw = m.L1I_MISS+m.L1D_MISS;  rv.per_cyc = cast(double)rv.raw/m.cycles; return rv; }

// a convenience to use all the metrics above as a list
alias Metrics = AliasSeq!(met_l1_miss);

void main(string[] argv)
{
	auto samples = iota(100);
	auto meas = new TI[samples.length];
	auto results = new TO[samples.length];

	// Initialize some values for the measured samples
	foreach(i, ref m; meas){
		m.L1D_MISS= 100+i; m.L1I_MISS=100-i; m.cycles= 10+i;
	}

    ref TI getTerm(int i)
    {
        return meas[i];
    }

	// compute the metric results for the above measured sample values in parallel
	taskPool.amap!(Metrics)(std.algorithm.map!getTerm(samples),results);

	TO rv1 = met_l1_miss( meas[1]);

	writeln("measurements:", meas[1]);
	writeln("rv1:", rv1);
	writeln("results:", results[1]);

}
Comment 2 Jay Norwood 2015-10-01 19:29:24 UTC
Must have been my bug.  Inputs with named Tuple members also works.  I'm going to close this.

import std.algorithm, std.parallelism, std.range;
import std.typecons;
import std.meta;
import std.stdio;

// define some input measurement sample tuples and output metric tuples

alias TI = Tuple!(long, "L1I_MISS",long, "L1D_MISS", long, "cycles" );
alias TO = Tuple!(long, "raw", double, "per_cyc");

// various metric definitions
// using Tuples with defined names for each member, and use the names here in the metrics.
TO met_l1_miss ( ref TI m){ TO rv;  rv.raw = m.L1I_MISS+m.L1D_MISS;  rv.per_cyc = cast(double)rv.raw/m.cycles; return rv; }

// a convenience to use all the metrics above as a list
alias Metrics = AliasSeq!(met_l1_miss);

void main(string[] argv)
{
	auto samples = iota(100);
	auto meas = new TI[samples.length];
	auto results = new TO[samples.length];

	// Initialize some values for the measured samples
	foreach(i, ref m; meas){
		m.L1D_MISS= 100+i; m.L1I_MISS=100-i; m.cycles= 10+i;
	}

    ref TI getTerm(int i)
    {
        return meas[i];
    }

	// compute the metric results for the above measured sample values in parallel
	taskPool.amap!(Metrics)(std.algorithm.map!getTerm(samples),results);

	TO rv1 = met_l1_miss( meas[1]);

	writeln("measurements:", meas[1]);
	writeln("rv1:", rv1);
	writeln("results:", results[1]);

}
Comment 3 Jay Norwood 2015-10-01 19:31:19 UTC
results can't be a struct.  Needs to be a Tuple.