Thread overview
An error on trying to sort shared data using slice
Jan 28, 2013
Sparsh Mittal
Jan 28, 2013
bearophile
Jan 28, 2013
Sparsh Mittal
Jan 28, 2013
bearophile
Jan 28, 2013
Ali Çehreli
Jan 28, 2013
Sparsh Mittal
Jan 28, 2013
Ali Çehreli
Jan 28, 2013
Sparsh Mittal
January 28, 2013
Purpose: I am trying to sort only a range of values in an array of struct (the struct has two fields and I want to sort on one of its fields using myComp function below). However, I am getting this error:

../src/phobos/std/algorithm.d(7731): Error: cannot implicitly convert expression (assumeSorted(r)) of type SortedRange!(shared(intpair)[], myComp) to SortedRange!(shared(intpair[]), myComp)
./ParallelCode.d(223): Error: template instance ParallelCode.singleSlave.sort!(myComp, cast(SwapStrategy)0, shared(intpair[])) error instantiating
=================================
where my relevant code is:
=================================


struct intpair{
  int AllInts[2];
};
shared intpair [] distArray;

void main()
{
...
distArray = new shared intpair[number_of_lines];
...
}

void singleThreadFunction(...)
{
 bool myComp(shared intpair x,shared intpair y)
   {
     return x.AllInts[0] < y.AllInts[0];
   }
shared intpair[] tempSortArray = distArray[startRange..endRange+1];

/*line 223:*/   sort!(myComp)(tempSortArray);

}

Can you please help me. Thanks.
January 28, 2013
Sparsh Mittal:

It compiles if you remove the shared:


import std.stdio: sort;

struct Intpair {
    int[2] allInts;
}

/*shared*/ Intpair[] distArray;

void main() {
    enum numberOfLines = 10;
    distArray.length = numberOfLines;

    static bool myComp(in /*shared*/ Intpair x,
                       in /*shared*/ Intpair y) {
        return x.allInts[0] < y.allInts[0];
    }

    enum startRange = 1;
    enum endRange = 3;
    /*shared*/ auto tempSortArray =
        distArray[startRange .. endRange + 1];
    sort!myComp(tempSortArray);
}


Also, take a look a the common D style:
http://dlang.org/dstyle.html

Bye,
bearophile
January 28, 2013
Thanks for your reply and link (which I will try to follow).

However, I am trying to write a parallel program where I have a big array. Multiple (e.g. 2, 4, 8) threads do work on part of those arrays. Afterwards, they sort their portions of array and return the answer to main.

So, I have made global variable, which is shared array. I do not know if there is another way to tackle the problem.

When I don't use shared, the singleThreadFunction, which is executed by different threads, does not process the shared array. Thanks.
January 28, 2013
Sparsh Mittal:

> Thanks for your reply and link (which I will try to follow).

Good.


> However, I am trying to write a parallel program where I have a big array. Multiple (e.g. 2, 4, 8) threads do work on part of those arrays. Afterwards, they sort their portions of array and return the answer to main.
>
> So, I have made global variable, which is shared array. I do not know if there is another way to tackle the problem.

This shows one solution using many mutexes, but using only fewer of them is probably enough:
http://rosettacode.org/wiki/Atomic_updates#D

Bye,
bearophile
January 28, 2013
On 01/28/2013 07:01 AM, Sparsh Mittal wrote:

> However, I am trying to write a parallel program where I have a big
> array. Multiple (e.g. 2, 4, 8) threads do work on part of those arrays.
> Afterwards, they sort their portions of array and return the answer to
> main.

That sounds very much like parallelism. ;) Have you considered the std.parallelism module?

  http://dlang.org/phobos/std_parallelism.html

There are more examples of that module here:

  http://ddili.org/ders/d.en/parallelism.html

Ali

January 28, 2013
Thanks a lot. Actually, I am using std.concurrency, following your tutorial:
http://ddili.org/ders/d.en/concurrency.html. Thanks for that tutorial.

My requirement is to sort a portion of an array in each thread, such that there is no overlap b/w portions and all portions together make the whole array.

So I am taking array as shared. Currently, in each thread, I am taking a slice of that array to sort, although that slice is not shared, I am forced to take shared since compiler does not allow without it.

Can you suggest something, e.g. sorting only a portion of an array, without slicing? Thanks.

January 28, 2013
On 01/28/2013 12:33 PM, Sparsh Mittal wrote:

> My requirement is to sort a portion of an array in each thread, such
> that there is no overlap b/w portions and all portions together make the
> whole array.
>
> So I am taking array as shared. Currently, in each thread, I am taking a
> slice of that array to sort, although that slice is not shared, I am
> forced to take shared since compiler does not allow without it.

As I understand it, that's how it should work.

> Can you suggest something, e.g. sorting only a portion of an array,
> without slicing? Thanks.

Why not slicing? The following program probably what you have tried anyway. It is shamefully unmaintainable: :)

import std.stdio;
import std.concurrency;
import std.algorithm;

struct Done
{}

void sorter(Tid owner, shared(int)[] sliceToSort)
{
    sort(sliceToSort);
    owner.send(Done());
}

void main()
{
    shared numbers = [ 6, 5, 4, 3, 2, 1 ];

    spawn(&sorter, thisTid, numbers[0 .. $ / 2]);
    spawn(&sorter, thisTid, numbers[$ / 2 .. $]);

    receiveOnly!Done();
    receiveOnly!Done();

    writeln(numbers);
}

Both halves of the slice are sorted:

[4, 5, 6, 1, 2, 3]

Instead of making 'numbers' itself shared, you can cast the slices that you send to the workers as such:

    auto numbers = [ 6, 5, 4, 3, 2, 1 ];
// ...
    spawn(&sorter, thisTid, cast(shared)numbers[0 .. $ / 2]);


But then the rest of the code would not know that the elements of 'numbers' may be modified by other threads. Defining it as 'shared' makes it impossible to ignore that fact.

Ali

January 28, 2013
Thanks a lot. Your code is very valuable to explain the whole concept. I have changed my code based on it.