Adrià Arrufat
Adrià Arrufat

Reputation: 471

How to use multiple threads with shared data inside a loop in Vala?

I was wondering how I could take advantage of my cores to make loops run in parallel. Let's say I want to initialise all members of a big array to 1. To check if the initialisation was done correctly, at the end, I add all the values of the array, but I get a zero. How can I make threads share the data?

Here's my attempt:

class Worker {
    public uint64[] arr;
    public uint64 start;
    public uint64 end;
    public int val;

    public Worker (ref uint64[] arr, uint64 start, uint64 end, int val) {
        this.arr = arr;
        this.start = start;
        this.end = end;
        this.val = val;
    }
}

void initialize (Worker p) {
    for (var i = p.start; i <= p.end; i++) {
        p.arr[i] = p.val;
    }
}

int main (string[] args) {

    var num_proc = (int) get_num_processors ();
    stdout.printf ("Using %d threads\n", num_proc);
    uint64 n = 50000000;
    var arr = new uint64[n];
    ulong microseconds;
    double seconds;
    var timer = new Timer ();

    try {
        var threads = new ThreadPool<Worker>.with_owned_data ((ThreadPoolFunc<Worker>) initialize, num_proc, true);
        for (var i = 0; i < num_proc; i++) {
            uint64 start = i * (n / num_proc);
            uint64 end = (i + 1) * (n / num_proc) - 1;
            if (i == num_proc - 1) end += n % num_proc;
            print (@"Thread $(i + 1): start: $start, end: $end (amount: $(end - start + 1))\n");
            threads.add (new Worker (ref arr, start, end, 1));
        }
    } catch (ThreadError e) {
        stderr.printf ("%s\n", e.message);
    }

    uint64 sum = 0;
    for (uint64 i = 0; i < n; i++) {
        sum += arr[i];
    }
    stdout.printf ("sum: %llu\n", sum);

    timer.stop ();
    seconds = timer.elapsed (out microseconds);
    stdout.printf ("Time elapsed: %.3f seconds.\n", seconds);

    return 0;
}

Upvotes: 0

Views: 129

Answers (1)

Jens M&#252;hlenhoff
Jens M&#252;hlenhoff

Reputation: 14883

The array is copied here:

public Worker (ref uint64[] arr, uint64 start, uint64 end, int val) {
    this.arr = arr;
    this.start = start;
    this.end = end;
    this.val = val;
}

An assignment is creating a copy here. You can use an unowned variable to fix this:

class Worker {
    // The array is not owned by the worker!
    public unowned uint64[] arr;
    public uint64 start;
    public uint64 end;
    public int val;

    public Worker (ref uint64[] arr, uint64 start, uint64 end, int val) {
        this.arr = arr;
        this.start = start;
        this.end = end;
        this.val = val;
    }
}

Upvotes: 1

Related Questions