Files
leonarski_f e3782cabe4 Refinement GPU: atom densities uploaded only when some B moved, one device copy, positions through a pinned buffer
Every evaluation uploaded both copies of the atoms' densities (the gather's and the gradient's) and their
boxes, although in a positions-only minimisation no B changes between two Refits. The engine now keeps one
copy (the gradient kernel reads ModelDensityGPU's atoms and boxes), uploads it only where some atom's
density was made again, and sends the positions from a pinned buffer without waiting. The densities that
are made again (every atom in a B minimisation) and the grid positions are worked out on the refinement's
threads. Same bits.

9yl4: upload 3.29 -> 0.56 s, host side 1.29 -> 0.61 s, refinement 22.3 -> 17.7 s; 5reo 4.8 -> 4.4 s
(RTX 5080, -N 8, loaded box).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015CeEGgpKdfkCTJb3YNMJcu
(cherry picked from commit 46c3b67c91aee0aec3473b0fb1a4945c00bda070)
(cherry picked from commit 0aebc98110c8155932af647d6204891aec662294)
2026-10-26 01:38:22 +01:00

25 lines
1.6 KiB
C++

// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute <filip.leonarski@psi.ch>
// SPDX-License-Identifier: GPL-3.0-only
#pragma once
// Restrained refinement's targets on a GPU (CUDA builds only): the RefinementEngine of RefinementXray.h with
// everything per evaluation on the device - the atoms' density (ModelDensityGPU's gather), its transform, the
// symmetry composed in reciprocal space, the likelihood target, the derivative map by the inverse transform
// of the target's derivatives and every atom's gradient read off it, and the geometry restraints. The host
// passes positions in and gets one value and one gradient per atom back.
#include <memory>
#include "RefinementXray.h"
// The engine for refining `model` against `refl` on `device`, or null where the GPU cannot take this case (an
// atom's box wider than the cell, too many symmetry operators) or its memory is over `budget` bytes.
// `b_max`: the largest B an atom may reach, which the gather's reserve is sized for. Throws JFJochException on a
// CUDA failure. `nthreads`: the host threads that work out the atoms' densities.
std::unique_ptr<RefinementEngine> MakeRefinementEngineGPU(int device, const gemmi::UnitCell &cell,
const gemmi::SpaceGroup &sg, double d_min,
const RefinementReflections &refl,
const gemmi::Model &model, double b_max, size_t budget,
size_t *device_bytes = nullptr, size_t nthreads = 1);