NAME
Task::MemManager::View::PDL - Create PDL views of Task::MemManager buffers
VERSION
version 0.02
SYNOPSIS
use Task::MemManager::View::PDL; ## this will also import Task::MemManager
my $length = 10;
my $mem = Task::MemManager->new(
$length, 1,
{
init_value => 40,
death_stub => sub {
my ($obj_ref) = @_;
printf "\n ======> Killing 0x%8x <======\n", $obj_ref->{identifier};
},
#allocator => 'CMalloc',
}
);
# Create a PDL view of a Task::MemManager buffer
my $pdl_view = $mem->create_view('PDL');
# The same region as uint16_t
my $pdl_intview =
$mem->create_view( 'PDL', { pdl_type => 'short', view_name => 'PDL_short' } );
DESCRIPTION
This module provides an interface to create PDL views of Task::MemManager buffers. It uses Inline::C to interface with the PDL C API. The created views will share memory with the Task::MemManager buffers, so any changes made to the view may be reflected in the buffer and vice versa. The emphasis is on may because PDL may decide to copy the data to a new memory location for its own purposes, e.g. during a transformation operation. In that case, the view will no longer share memory with the original buffer. This opens up some interesting possibilities, e.g. using PDL to transform data in a buffer and then having Task::MemManager manage the transformed data. Refer to the examples to see what is possible.
METHODS
create_view
Usage : $view = $buffer->create_view($buffer_address, $buffer_size \%options);
Purpose : Create a PDL view of the specified type for the buffer
Returns : The created view (a PDL ndarray) or undef on failure
The view is created using the buffer's memory.
Parameters : $buffer_address - address of the buffer's memory
$buffer_size - size of the buffer's memory in bytes
\%options - hash reference with options for the view. The
supported options are:
pdl_type - the PDL type of the view. Default is 'byte'.
See the %PDL_types hash for the supported types.
dims - array reference with the dimensions of the view.
Default is a one-dimensional view with as many
elements as fit in the buffer.
Throws : The function will die if an unknown PDL type is specified.
It will warn (but not die) if the buffer size is not a
multiple of the requested number of elements times the
element size.
Comments : Returns undef if the view creation fails for any reason (e.g.
stuff happening inside PDL).
Warnings will be generated if DEBUG is set to a non-zero value.
The standard PDL types are supported during view creation. The size of these types is hardcoded in the %PDL_types hash, except for 'indx', 'ldouble', and 'cldouble', which are determined at runtime using the sizeof operator. The sizes below are based on GCC in an x86_64 environment and may need to be adjusted for other compilers:
my %PDL_types = (
sbyte => [ 0, 1 ],
byte => [ 1, 1 ],
short => [ 2, 2 ],
ushort => [ 3, 2 ],
long => [ 4, 4 ],
ulong => [ 5, 4 ],
indx => [ 6, 4 ],
ulonglong => [ 7, 8 ],
longlong => [ 8, 8 ],
float => [ 9, 4 ],
double => [ 10, 8 ],
ldouble => [ 11, 8 ],
cfloat => [ 12, 8 ],
cdouble => [ 13, 8 ],
cldouble => [ 14, 16 ],
);
The hash keys are the PDL type names and the values are [ type_code, size_in_bytes ].
clone_view
Usage : $view_clone = $view->clone_view();
Purpose : Clone a PDL view
Returns : The cloned view
Parameters : $view - the PDL view to clone
Throws : Nothing
Comments : The cloned view will NOT share memory with the original view.
This is a deep copy.
EXAMPLES
Some of the examples are assumed to run sequentially, i.e. the same buffer is used in multiple examples.
Example 1: Creating views
use Task::MemManager;
use Task::MemManager::View::PDL;
my $buffer = Task::MemManager->new_buffer(1024);
my $view = $buffer->create_view(0, 1024, { pdl_type => 'float', dims => [ 256, 4 ] });
if ($view) {
print "Created PDL view successfully\n";
} else {
print "Failed to create PDL view\n";
}
Example 2: Accessing and modifying data through the view
use Task::MemManager;
use Task::MemManager::View ;
use PDL;
use PDL::NiceSlice;
my $length = 10;
my $mem = Task::MemManager->new(
$length, 1,
{
init_value => 40,
death_stub => sub {
my ($obj_ref) = @_;
printf "\n ======> Killing 0x%8x <======\n", $obj_ref->{identifier};
},
}
);
# allows to print hex values of a string
sub print_hex_values {
my ( $string, $bytes_per_line ) = @_;
$bytes_per_line //= 8; # Default to 8 bytes per line if not provided
my @bytes =
unpack( 'C*', $string ); # Unpack the string into a list of bytes
for ( my $i = 0 ; $i < @bytes ; $i++ ) {
printf( "%02X ", $bytes[$i] ); # Print each byte in hexadecimal format
print "\n"
if ( ( $i + 1 ) % $bytes_per_line == 0 )
; # Print a newline after every $bytes_per_line bytes
}
print "\n"
if ( @bytes % $bytes_per_line != 0 )
; # Print a final newline if the last line wasn't complete
}
my $task_buffer = $mem->get_buffer();
my $pdl_view = $mem->create_view('PDL');
say $pdl_view;
print_hex_values($mem->extract_buffer_region(0,9),10);
Output should be (40 is 0x28 in hex):
[40 40 40 40 40 40 40 40 40 40]
28 28 28 28 28 28 28 28 28 28
Example 3: Modifying the PDL view in place, modifies the buffer
This continues from Example 2.
$pdl_view(0:4).=20;
$pdl_view +=1; # implied in place
say $pdl_view->inplace->sqrt; # PDL view
print_hex_values($mem->extract_buffer_region(0,9),10); # stored Task::MemManager object
say $mem->get_view('PDL_default'); # view through Task::MemManager
All three outputs should be identical:
[4 4 4 4 4 6 6 6 6 6]
04 04 04 04 04 06 06 06 06 06
[4 4 4 4 4 6 6 6 6 6]
Example 4: Cloning a view
say $mem->get_view('PDL_default');
say "Clone the view and increment it by one";
my $pdl_clone= $mem->clone_view('PDL_default');
say "Get an uint16_t view";
my $pdl_intview=$mem->create_view('PDL',{pdl_type=>'short',view_name=>'PDL_short'});
say "Initial View : ",$pdl_view;
say " Cloned View : ", $pdl_clone;
say " Int32 View : ",$pdl_intview;
Output should be:
Clone the view and increment it by one
Get an uint16_t view
Initial View : [4 4 4 4 4 6 6 6 6 6]
Cloned View : [4 4 4 4 4 6 6 6 6 6]
Int32 View : [1028 1028 1540 1542 1542]
DIAGNOSTICS
If you set up the environment variable DEBUG to a non-zero value, then a number of sanity checks will be performed, and the module will carp with an (informative message ?) if something is wrong.
DEPENDENCIES
The module extends the Task::MemManager::View
module so this is definitely a dependency. It (obviously) requires the PDL
(Perl Data Language) module to be installed and the Inline::C
module to interface with the PDL C API.
TODO
Open to suggestions. One idea is to add Magic to the views to support various operations triggered via accessing or modifying the view. For example, one could support GPU memory mapping.
SEE ALSO
https://metacpan.org/pod/Task::MemManager
This module exports various internal perl methods that change the internal representation or state of a perl scalar. All of these work in-place, that is, they modify their scalar argument.
https://metacpan.org/pod/Task::MemManager::View
This module provides an interface to create views of Task::MemManager buffers using various data processing libraries.
https://metacpan.org/pod/Inline::C
Inline::C is a module that allows you to write Perl subroutines in C.
https://perldoc.perl.org/perlguts
Introduction to the Perl API.
https://perldoc.perl.org/perlapi
Autogenerated documentation for the perl public API.
AUTHOR
Christos Argyropoulos, <chrisarg at cpan.org>
COPYRIGHT AND LICENSE
This software is copyright (c) 2025 by Christos Argyropoulos.
This is free software; you can redistribute it and/or modify it under the MIT license. The full text of the license can be found in the LICENSE file See https://en.wikipedia.org/wiki/MIT_License for more information.