AI-MXNet
view release on metacpan or search on metacpan
lib/AI/MXNet/Executor/Group.pm view on Meta::CPAN
Parameters
----------
$data_shapes : ArrayRef[AI::MXNet::DataDesc]
$label_shapes : Maybe[ArrayRef[AI::MXNet::DataDesc]]
=cut
method reshape(
ArrayRef[AI::MXNet::DataDesc] $data_shapes,
Maybe[ArrayRef[AI::MXNet::DataDesc]] $label_shapes=
)
{
return if($data_shapes eq $self->data_shapes and $label_shapes eq $self->label_shapes);
if (not defined $self->_p->_default_execs)
{
$self->_p->_default_execs([@{ $self->_p->execs }]);
}
$self->bind_exec($data_shapes, $label_shapes, undef, 1);
}
=head2 set_params
Assign, i.e. copy parameters to all the executors.
Parameters
----------
$arg_params : HashRef[AI::MXNet::NDArray]
A dictionary of name to AI::MXNet::NDArray parameter mapping.
$aux_params : HashRef[AI::MXNet::NDArray]
A dictionary of name to AI::MXNet::NDArray auxiliary variable mapping.
=cut
method set_params(HashRef[AI::MXNet::NDArray] $arg_params, HashRef[AI::MXNet::NDArray] $aux_params, Bool $allow_extra=0)
{
$_->copy_params_from($arg_params, $aux_params, $allow_extra) for @{ $self->_p->execs };
}
=head2 get_params
Copy data from each executor to arg_params and aux_params.
Parameters
----------
$arg_params : HashRef[AI::MXNet::NDArray]
target parameter arrays
$aux_params : HashRef[AI::MXNet::NDArray]
target aux arrays
Notes
-----
- This function will inplace update the NDArrays in arg_params and aux_params.
=cut
method get_params(HashRef[AI::MXNet::NDArray] $arg_params, HashRef[AI::MXNet::NDArray] $aux_params)
{
my $weight = 0;
zip(sub {
my ($name, $block) = @_;
my $weight = sum(map { $_->copyto(AI::MXNet::Context->cpu) } @{ $block }) / @{ $block };
$weight->astype($arg_params->{$name}->dtype)->copyto($arg_params->{$name});
}, $self->param_names, $self->_p->param_arrays);
zip(sub {
my ($name, $block) = @_;
my $weight = sum(map { $_->copyto(AI::MXNet::Context->cpu) } @{ $block }) / @{ $block };
$weight->astype($aux_params->{$name}->dtype)->copyto($aux_params->{$name});
}, $self->_p->aux_names, $self->_p->aux_arrays);
}
method get_states($merge_multi_context=1)
{
assert((not $merge_multi_context), "merge_multi_context=True is not supported for get_states yet.");
return $self->_p->state_arrays;
}
method set_states($states, $value)
{
if(defined $states)
{
assert((not defined $value), "Only one of states & value can be specified.");
AI::MXNet::Executor::Group::_load_general($states, $self->_p->state_arrays, [(0)x@{ $states }]);
}
else
{
assert((defined $value), "At least one of states & value must be specified.");
assert((not defined $states), "Only one of states & value can be specified.");
for my $d_dst (@{ $self->_p->state_arrays })
{
for my $dst (@{ $d_dst })
{
$dst .= $value;
}
}
}
}
=head2 forward
Split the data_batch according to a workload and run forward on each devices.
Parameters
----------
data_batch : AI::MXNet::DataBatch
Or could be any object implementing similar interface.
is_train : bool
The hint for the backend, indicating whether we are during training phase.
Default is undef, then the value $self->for_training will be used.
=cut
method forward(AI::MXNet::DataBatch $data_batch, Maybe[Bool] $is_train=)
{
AI::MXNet::Executor::Group::_load_data($data_batch, $self->_p->data_arrays, $self->_p->data_layouts);
$is_train //= $self->for_training;
if(defined $self->_p->label_arrays)
{
confess("assert not is_train or data_batch.label")
unless (not $is_train or $data_batch->label);
if($data_batch->label)
{
AI::MXNet::Executor::Group::_load_label($data_batch, $self->_p->label_arrays, $self->_p->label_layouts);
}
}
lib/AI/MXNet/Executor/Group.pm view on Meta::CPAN
}, [0..@{ $self->_p->execs }-1], $self->_p->execs, $self->_p->slices);
}
=head2 update_metric
Accumulate the performance according to eval_metric on all devices.
Parameters
----------
eval_metric : AI::MXNet::EvalMetric
The metric used for evaluation.
labels : array ref of NDArray
Typically comes from label of AI::MXNet::DataBatch.
=cut
method update_metric(AI::MXNet::EvalMetric $eval_metric, ArrayRef[AI::MXNet::NDArray] $labels)
{
zip(sub {
my ($texec, $islice) = @_;
my @labels_slice;
zip(sub {
my ($label, $axis) = @_;
if($axis == 0)
{
# slicing NDArray along axis 0 can avoid copying
push @labels_slice, $label->slice([$islice->[0], $islice->[1]-1]);
}
elsif($axis > 0)
{
my $label_my_slice = $label->slice_axis({
axis => $axis,
begin => $islice->[0],
end => $islice->[1]
})->as_in_context($label->context);
push @labels_slice, $label_my_slice;
}
else
{
push @labels_slice, $label;
}
}, $labels, $self->_p->label_layouts);
$eval_metric->update(\@labels_slice, $texec->outputs);
}, $self->_p->execs, $self->_p->slices);
}
method _bind_ith_exec(
Int $i,
ArrayRef[AI::MXNet::DataDesc] $data_shapes,
Maybe[ArrayRef[AI::MXNet::DataDesc]] $label_shapes,
Maybe[AI::MXNet::DataParallelExecutorGroup] $shared_group
)
{
my $shared_exec = $shared_group ? $shared_group->_p->execs->[$i] : undef;
my $context = $self->contexts->[$i];
my $shared_data_arrays = $self->_p->shared_data_arrays->[$i];
my %input_shapes = map { $_->name => $_->shape } @{ $data_shapes };
if(defined $label_shapes)
{
%input_shapes = (%input_shapes, map { $_->name => $_->shape } @{ $label_shapes });
}
my %input_types = map { $_->name => $_->dtype } @{ $data_shapes };
my $executor = $self->symbol->simple_bind(
ctx => $context,
grad_req => $self->grad_req,
type_dict => \%input_types,
shared_arg_names => $self->param_names,
shared_exec => $shared_exec,
shared_buffer => $shared_data_arrays,
shapes => \%input_shapes
);
return $executor;
}
=head2 _sliced_shape
Get the sliced shapes for the i-th executor.
Parameters
----------
shapes : array ref of (str, array ref)
The original (name, shape) pairs.
i : int
Which executor we are dealing with.
=cut
method _sliced_shape(ArrayRef[AI::MXNet::DataDesc] $shapes, Int $i, ArrayRef[Int] $major_axis)
{
my @sliced_shapes;
zip(sub {
my ($desc, $axis) = @_;
my @shape = @{ $desc->shape };
if($axis >= 0)
{
$shape[$axis] = $self->_p->slices->[$i]->[1] - $self->_p->slices->[$i]->[0];
}
push @sliced_shapes, AI::MXNet::DataDesc->new(
name => $desc->name,
shape => \@shape,
dtype => $desc->dtype,
layout => $desc->layout
);
}, $shapes, $major_axis);
return \@sliced_shapes;
}
=head2 install_monitor
Install monitor on all executors
Parameters
----------
$mon : AI::MXNet::Monitor
=cut
method install_monitor(AI::MXNet::Monitor $mon)
{
$mon->install($_) for @{ $self->_p->execs };
}
method shared_data_arrays()
{
$self->_p->shared_data_arrays;
}
method execs()
{
$self->_p->execs;
}
1;
( run in 1.311 second using v1.01-cache-2.11-cpan-df04353d9ac )