Efficient way of passing num arrays to C from Raku

146 views Asked by At

The code presented here is simple to illustrate a use case. I want to know the efficient ways of passing an array of num to C from Raku.

#include <stdio.h>
#include <omp.h>
void c_sum_two(double *first, double *second, double *third, int num)
{
    #pragma omp parallel for
    for (int i = 0; i < num; i++)
    {
        third[i] = first[i] + second[i];
    }
}

What this does is: passes first and second array from Raku to C, performs some calculation, in this case (addition using openmp) and returns a num array to raku.

use NativeCall;
constant MYDYN = "./testsum.dll";

sub c_sum_two(CArray[num64], CArray[num64],CArray[num64], int32) 
    is native( MYDYN) { * };

sub native_sum_two(@arr_one is copy, @arr_two is copy) {
    my $elems = @arr_one.elems;
    ##======================================================##
    # check if two array have same elems
    ##======================================================##
    # Prepare arrays for passing to C
    ##======================================================##
    @arr_one = @arr_one.map: {$_.Num};
    @arr_two = @arr_two.map: {$_.Num};
    # handling first array
    my $first = CArray[num64].new(@arr_one);
    # handling second array
    my $second = CArray[num64].new(@arr_two);
    ##======================================================##
    # Prepare for return array
    my $return = CArray[num64].allocate($elems);
    ##======================================================##
    # Call the C function
    c_sum_two($first, $second, $return, $elems);
    ##======================================================##
    # Get the output back
    $return.list
}

my @a = <1.2 2 3.2 10 0.33>;
my @b = <2 12 18 10 8>;
say native_sum_two(@a, @b) # (3.2 14 21.2 20 8.33)

While preparing for passing arrays to C, I am converting each value of two arrays to Num (O(n) + O(n) time).

  • Is this the right efficient way of doing this?
  • Is there other way to directly lay the array as num in memory?
  • Also is there another better way of returning array?

May be due to the overhead, I am not getting the speedup compared to the same thing in raku:

my @c;
for [email protected] {
    @c[$_] = @a[$_] + @b[$_];

}
say @c
1

There are 1 answers

1
Cem Polat On

you can avoid creating the intermediate Num arrays and use the NativeCall CArray constructor with your original arrays directly.

sub native_sum_two(@arr_one is copy, @arr_two is copy) {
    my $elems = @arr_one.elems;

    # Create CArray directly from Raku arrays
    my $first = CArray[num64].new(@arr_one».Num);
    my $second = CArray[num64].new(@arr_two».Num);

    # Prepare for the return array
    my $return = CArray[num64].allocate($elems);

    # Call the C function
    c_sum_two($first, $second, $return, $elems);

    # Get the output back
    $return.list
}