% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/ag_training.R
\name{dp_train}
\alias{dp_train}
\title{Data-parallel training across multiple GPUs}
\usage{
dp_train(
  make_model,
  data,
  loss_fn = NULL,
  forward_fn = NULL,
  target_fn = NULL,
  n_gpu = NULL,
  n_iter = 10L,
  lr = 0.001,
  max_norm = Inf,
  verbose = 10L
)
}
\arguments{
\item{make_model}{A zero-argument function that returns a model object with
at least \code{$forward(x)} and \code{$parameters()} methods.  Called
\code{n_gpu} times; each call must produce independent parameters.}

\item{data}{A list of training samples.  Each element is passed directly to
\code{forward_fn} (or to \code{model$forward()} if \code{forward_fn} is
\code{NULL}).}

\item{loss_fn}{A function \code{(logits, target) -> scalar ag_tensor}.
If \code{NULL}, \code{forward_fn} must return the loss directly.}

\item{forward_fn}{Optional function \code{(model, sample) -> logits}.
If \code{NULL}, the sample is passed directly as
\code{model$forward(sample)}.}

\item{target_fn}{Optional function \code{(sample) -> target}.  Used when
\code{loss_fn} is not \code{NULL} to extract the target from a sample.
If \code{NULL}, \code{sample} itself is used as the target.}

\item{n_gpu}{Number of GPU replicas (default: all available Vulkan devices,
minimum 1).}

\item{n_iter}{Number of training iterations (passes over \code{data}).}

\item{lr}{Learning rate for Adam optimizer (default 1e-3).}

\item{max_norm}{Gradient clipping threshold (default \code{Inf} = no clip).}

\item{verbose}{Print loss every \code{verbose} iterations, or \code{FALSE}
to suppress output.}
}
\value{
A list with:
  \describe{
    \item{\code{params}}{Named list of final parameters (from replica 0).}
    \item{\code{loss_history}}{Numeric vector of per-iteration mean loss.}
    \item{\code{model}}{Replica 0 model object.}
  }
}
\description{
Runs synchronous data-parallel training:
\enumerate{
  \item \code{make_model()} is called \code{n_gpu} times to create one
    independent model replica per GPU (each with its own parameters).
  \item Each iteration: the current data item is forwarded through every
    replica in parallel; gradients are computed via \code{backward()}.
  \item Gradients are averaged across all replicas (element-wise mean).
  \item One optimizer step is taken on replica 0; updated weights are then
    broadcast to replicas 1 … N-1 so all replicas stay in sync.
}
}
\details{
Because all replicas live in the same R process and \code{ag_param} uses
environment (reference) semantics, no IPC or NCCL is required — weight
synchronisation is a simple in-place copy.
}
\examples{
\donttest{
make_model <- function() {
  W <- ag_param(matrix(rnorm(4), 2, 2))
  list(
    forward    = function(x) ag_matmul(W, x),
    parameters = function() list(W = W)
  )
}
data <- lapply(1:8, function(i) matrix(rnorm(2), 2, 1))
result <- dp_train(
  make_model = make_model,
  data       = data,
  loss_fn    = function(out, tgt) ag_mse_loss(out, tgt),
  target_fn  = function(s) s,
  n_gpu      = 1L,
  n_iter     = 10L,
  lr         = 1e-3,
  verbose    = FALSE
)
}
}
