Advent Calendar 2020
| Day 15 | Day 16 | Day 17 |
The gift is presented by Yet Ebreo. Today he is talking about his solution to the task Calling C function
of “The Weekly Challenge - 029”. This is re-produced for Advent Calendar 2020 from the original post by Yet Ebreo.
Write a script to demonstrate calling a C function. It could be any user defined or standard C function.
I have seen implementation of this using the Inline module but I have to be honest that I have never really tried it in perl. Never had the need to use it or atleast that’s what I thought. At the back of my mind, I knew a piece of code compiled in C would perform better compared to pure perl solution.
Solution:
So for this task, I created a fibonacci function (both in C and Perl) that would take a number $n
as input and would return the n-th
number in the fibonacci series.
I used the Inline
module and wrote the C function after the special literals __END__
and __C__
.
a) END indicates the logical end of the script before the actual end of file. Any following text is ignored.
b) C indicates the start of the C code
The perl_fib
function is the pure perl version of the fibonacci function and fib is the C version.
I knew the Perl implementation would take longer to finish (vs C) on bigger input range; so I took the oppurtunity to use the Memoize
module to compare the performances of:
a) perl_fib - function writtern in perl without Memoize
b) perl_fib(Memoized) - same function but Memoized
c) fib - function written in C
Code:
#!/usr/bin/env perl
# Write a script to demonstrate calling a C function.
# It could be any user defined or standard C function.
use strict;
use warnings;
use feature 'say';
use Memoize;
use Inline 'C';
my $start_run;
my $run_time;
$start_run = time();
print (perl_fib($_)." ") for 1..36;
$run_time = time() - $start_run;
say "\nRun Time (Perl): $run_time sec\n";
memoize('perl_fib');
$start_run = time();
print (perl_fib($_)." ") for 1..36;
$run_time = time() - $start_run;
say "\nRun Time (Perl-Memoized): $run_time sec\n";
$start_run = time();
print (fib($_)." ") for 1..36;
$run_time = time() - $start_run;
say "\nRun Time (Inline-C): $run_time sec\n";
sub perl_fib { (
$_[0] == 0) ?
0: ($_[0] == 1)?
1:perl_fib($_[0]-1)+perl_fib($_[0]-2)
}
__END__
__C__
unsigned long fib(int n) {
if ( n == 0 )
return 0;
else if ( n == 1 )
return 1;
else
return ( fib(n-1) + fib(n-2) );
}
Output:
$ perl ch-2.pl
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025
121393 196418 317811 514229 832040 1346269 2178309 3524578 5702887 9227465 14930352
Run Time (Perl): 49 sec
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025
121393 196418 317811 514229 832040 1346269 2178309 3524578 5702887 9227465 14930352
Run Time (Perl-Memoized): 0 sec
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765 10946 17711 28657 46368 75025
121393 196418 317811 514229 832040 1346269 2178309 3524578 5702887 9227465 14930352
Run Time (Inline-C): 1 sec
As expected, the Perl implementation took the longer compared to the C version. But it is surprising how Memoize
cut down the execution time to just a fraction of a second.
And that’s it for this week’s challenge. If you’d like to join the fun and contribute, please visit the site managed by Mohammad S Anwar.
If you have any suggestion then please do share with us perlweeklychallenge@yahoo.com.