Stabilize cached Z4C CUDA sync after regrid

This commit is contained in:
2026-05-01 20:04:04 +08:00
parent 30b778daa3
commit 531b31e8db
5 changed files with 833 additions and 79 deletions

View File

@@ -16,7 +16,7 @@
#if USE_CUDA_BSSN || USE_CUDA_Z4C
#include <cuda_runtime_api.h>
#endif
#if USE_CUDA_BSSN
#if USE_CUDA_BSSN || USE_CUDA_Z4C
#include "bssn_rhs_cuda.h"
#endif
#if USE_CUDA_Z4C
@@ -191,26 +191,26 @@ bool cuda_build_bssn_host_views(Block *block,
}
return v == 0;
}
#endif
bool cuda_build_bssn_soa(MyList<var> *vars,
int state_count,
double *soa_flat)
bool cuda_build_state_soa(MyList<var> *vars,
int state_count,
double *soa_flat)
{
if (!vars || !soa_flat || state_count != BSSN_CUDA_STATE_COUNT)
return false;
MyList<var> *v = vars;
for (int i = 0; i < BSSN_CUDA_STATE_COUNT; ++i)
{
if (!v)
return false;
if (!vars || !soa_flat || state_count <= 0)
return false;
MyList<var> *v = vars;
for (int i = 0; i < state_count; ++i)
{
if (!v)
return false;
soa_flat[3 * i + 0] = v->data->SoA[0];
soa_flat[3 * i + 1] = v->data->SoA[1];
soa_flat[3 * i + 2] = v->data->SoA[2];
v = v->next;
}
return v == 0;
}
return v == 0;
}
#endif
#if USE_CUDA_BSSN || USE_CUDA_Z4C
int fortran_idint(double x)
@@ -231,7 +231,7 @@ bool cuda_cell_gw3_restrict_params(const Parallel::gridseg *src,
const Parallel::gridseg *dst,
int first_fine[3])
{
#if USE_CUDA_BSSN && defined(Cell) && (ghost_width == 3)
#if (USE_CUDA_BSSN || USE_CUDA_Z4C) && defined(Cell) && (ghost_width == 3)
if (!src || !dst || !src->Bg || !dst->Bg)
return false;
for (int d = 0; d < dim; ++d)
@@ -272,7 +272,7 @@ bool cuda_cell_gw3_prolong_params(const Parallel::gridseg *src,
int first_fine_ii[3],
int coarse_lb[3])
{
#if USE_CUDA_BSSN && defined(Cell) && (ghost_width == 3)
#if (USE_CUDA_BSSN || USE_CUDA_Z4C) && defined(Cell) && (ghost_width == 3)
if (!src || !dst || !src->Bg || !dst->Bg)
return false;
for (int d = 0; d < dim; ++d)
@@ -330,7 +330,30 @@ bool cuda_can_direct_pack(const Parallel::gridseg *src, const Parallel::gridseg
return false;
#if USE_CUDA_Z4C && (ABEtype == 2)
if (type != 1)
{
static int z4c_amr_device = -1;
if (z4c_amr_device < 0)
{
const char *env = getenv("AMSS_CUDA_Z4C_AMR_DEVICE");
z4c_amr_device = (env && atoi(env) != 0) ? 1 : 0;
}
if (!z4c_amr_device)
return false;
}
if (type == 2 && !cuda_amr_restrict_device_enabled())
return false;
if (type == 3 && !cuda_amr_prolong_device_enabled())
return false;
if (type == 2) {
int a[3];
if (!cuda_cell_gw3_restrict_params(src, dst, a))
return false;
}
if (type == 3) {
int a[3], b[3];
if (!cuda_cell_gw3_prolong_params(src, dst, a, b))
return false;
}
return z4c_cuda_has_resident_state(src->Bg) != 0;
#elif USE_CUDA_BSSN
if (bssn_cuda_has_resident_state(src->Bg) == 0)
@@ -362,8 +385,6 @@ bool cuda_can_direct_unpack(const Parallel::gridseg *dst, int type)
if (type < 1 || type > 3 || !dst || !dst->Bg)
return false;
#if USE_CUDA_Z4C && (ABEtype == 2)
if (type != 1)
return false;
return z4c_cuda_has_resident_state(dst->Bg) != 0;
#elif USE_CUDA_BSSN
return bssn_cuda_has_resident_state(dst->Bg) != 0;
@@ -611,16 +632,43 @@ bool cuda_direct_pack_segment_to_device(double *buffer,
#if USE_CUDA_Z4C && (ABEtype == 2)
if (state_count == Z4C_CUDA_STATE_COUNT)
{
if (type != 1)
return false;
const double t0 = sync_profile_enabled() ? MPI_Wtime() : 0.0;
const int i0 = cuda_seg_begin(dst, src->Bg, 0);
const int j0 = cuda_seg_begin(dst, src->Bg, 1);
const int k0 = cuda_seg_begin(dst, src->Bg, 2);
const bool ok = z4c_cuda_pack_state_batch_to_device_buffer(
src->Bg, state_count, buffer, src->Bg->shape,
i0, j0, k0,
dst->shape[0], dst->shape[1], dst->shape[2]) == 0;
bool ok = false;
double soa_flat[3 * Z4C_CUDA_STATE_COUNT];
const bool have_soa = cuda_build_state_soa(VarLists, state_count, soa_flat);
if (type == 1)
{
const int i0 = cuda_seg_begin(dst, src->Bg, 0);
const int j0 = cuda_seg_begin(dst, src->Bg, 1);
const int k0 = cuda_seg_begin(dst, src->Bg, 2);
ok = z4c_cuda_pack_state_batch_to_device_buffer(
src->Bg, state_count, buffer, src->Bg->shape,
i0, j0, k0,
dst->shape[0], dst->shape[1], dst->shape[2]) == 0;
}
else if (type == 2)
{
int first_fine[3];
if (!cuda_cell_gw3_restrict_params(src, dst, first_fine))
return false;
ok = z4c_cuda_restrict_state_batch_to_device_buffer(
src->Bg, state_count, buffer, src->Bg->shape,
dst->shape[0], dst->shape[1], dst->shape[2],
first_fine[0], first_fine[1], first_fine[2],
have_soa ? soa_flat : 0) == 0;
}
else if (type == 3)
{
int first_fine_ii[3], coarse_lb[3];
if (!cuda_cell_gw3_prolong_params(src, dst, first_fine_ii, coarse_lb))
return false;
ok = z4c_cuda_prolong_state_batch_to_device_buffer(
src->Bg, state_count, buffer, src->Bg->shape,
dst->shape[0], dst->shape[1], dst->shape[2],
first_fine_ii[0], first_fine_ii[1], first_fine_ii[2],
coarse_lb[0], coarse_lb[1], coarse_lb[2],
have_soa ? soa_flat : 0) == 0;
}
if (sync_profile_enabled())
sync_profile_stats().direct_pack_sec += MPI_Wtime() - t0;
return ok;
@@ -634,7 +682,7 @@ bool cuda_direct_pack_segment_to_device(double *buffer,
double *views[BSSN_CUDA_STATE_COUNT];
double soa_flat[3 * BSSN_CUDA_STATE_COUNT];
const bool have_views = cuda_build_bssn_host_views(src->Bg, VarLists, state_count, views);
const bool have_soa = cuda_build_bssn_soa(VarLists, state_count, soa_flat);
const bool have_soa = cuda_build_state_soa(VarLists, state_count, soa_flat);
if (type == 1)
{
const int i0 = cuda_seg_begin(dst, src->Bg, 0);
@@ -842,6 +890,29 @@ bool cuda_download_resident_subset_to_host(Block *block,
MyList<var> *vars,
int state_count)
{
#if USE_CUDA_Z4C && (ABEtype == 2)
if (state_count == Z4C_CUDA_STATE_COUNT)
{
if (!block || !vars)
return false;
if (z4c_cuda_has_resident_state(block) == 0)
return true;
int indices[Z4C_CUDA_STATE_COUNT];
double *views[Z4C_CUDA_STATE_COUNT];
MyList<var> *v = vars;
for (int i = 0; i < state_count; ++i)
{
if (!v)
return false;
indices[i] = i;
views[i] = block->fgfs[v->data->sgfn];
if (!views[i])
return false;
v = v->next;
}
return z4c_cuda_download_state_subset(block, block->shape, state_count, indices, views) == 0;
}
#endif
#if USE_CUDA_BSSN
if (!block || state_count <= 0 || state_count > BSSN_CUDA_STATE_COUNT)
return false;
@@ -870,7 +941,23 @@ bool cuda_unpack_host_region_to_resident(Block *block,
double *buffer,
const Parallel::gridseg *dst)
{
#if USE_CUDA_BSSN
#if USE_CUDA_Z4C && (ABEtype == 2)
if (block && dst && state_index >= 0 && state_index < Z4C_CUDA_STATE_COUNT &&
z4c_cuda_has_resident_state(block) == 0)
return true;
if (block && dst && state_index >= 0 && state_index < Z4C_CUDA_STATE_COUNT &&
z4c_cuda_has_resident_state(block) != 0)
{
const int i0 = cuda_seg_begin(dst, block, 0);
const int j0 = cuda_seg_begin(dst, block, 1);
const int k0 = cuda_seg_begin(dst, block, 2);
return z4c_cuda_unpack_state_region_from_host_buffer(
block, state_index, buffer, block->shape,
i0, j0, k0,
dst->shape[0], dst->shape[1], dst->shape[2]) == 0;
}
#endif
#if USE_CUDA_BSSN
if (!block || !dst || state_index < 0 || state_index >= BSSN_CUDA_STATE_COUNT)
return false;
if (bssn_cuda_has_resident_state(block) == 0)
@@ -902,7 +989,7 @@ bool cuda_device_state_count_supported(int state_count)
#endif
}
#if USE_CUDA_BSSN
#if USE_CUDA_BSSN || USE_CUDA_Z4C
bool cuda_flush_device_segment_batch(Block *block,
double *data,
int state_count,
@@ -913,12 +1000,35 @@ bool cuda_flush_device_segment_batch(Block *block,
{
if (!block || meta.empty())
return true;
const int stride = (dir == PACK && type == 3) ? 11 : 8;
const int segment_count = (int)(meta.size() / stride);
double *views[BSSN_CUDA_STATE_COUNT];
double soa_flat[3 * BSSN_CUDA_STATE_COUNT];
const bool have_views = cuda_build_bssn_host_views(block, vars, state_count, views);
const bool have_soa = cuda_build_bssn_soa(vars, state_count, soa_flat);
const int stride = (dir == PACK && type == 3) ? 11 : 8;
const int segment_count = (int)(meta.size() / stride);
#if USE_CUDA_Z4C && (ABEtype == 2)
if (state_count == Z4C_CUDA_STATE_COUNT)
{
double soa_flat[3 * Z4C_CUDA_STATE_COUNT];
const bool have_soa = cuda_build_state_soa(vars, state_count, soa_flat);
if (dir == PACK)
{
if (type == 2)
return z4c_cuda_restrict_state_segments_to_device_buffer(
block, state_count, data, block->shape, segment_count,
meta.data(), have_soa ? soa_flat : 0) == 0;
if (type == 3)
return z4c_cuda_prolong_state_segments_to_device_buffer(
block, state_count, data, block->shape, segment_count,
meta.data(), have_soa ? soa_flat : 0) == 0;
return z4c_cuda_pack_state_segments_to_device_buffer(
block, state_count, data, block->shape, segment_count, meta.data()) == 0;
}
return z4c_cuda_unpack_state_segments_from_device_buffer(
block, state_count, data, block->shape, segment_count, meta.data()) == 0;
}
#endif
#if USE_CUDA_BSSN
double *views[BSSN_CUDA_STATE_COUNT];
double soa_flat[3 * BSSN_CUDA_STATE_COUNT];
const bool have_views = cuda_build_bssn_host_views(block, vars, state_count, views);
const bool have_soa = cuda_build_state_soa(vars, state_count, soa_flat);
if (dir == PACK)
{
if (type == 2)
@@ -941,11 +1051,15 @@ bool cuda_flush_device_segment_batch(Block *block,
: bssn_cuda_pack_state_segments_to_device_buffer(
block, state_count, data, block->shape, segment_count, meta.data()) == 0;
}
return have_views
? bssn_cuda_unpack_state_segments_from_device_buffer_for_host_views(
block, views, state_count, data, block->shape, segment_count, meta.data()) == 0
: bssn_cuda_unpack_state_segments_from_device_buffer(
block, state_count, data, block->shape, segment_count, meta.data()) == 0;
return have_views
? bssn_cuda_unpack_state_segments_from_device_buffer_for_host_views(
block, views, state_count, data, block->shape, segment_count, meta.data()) == 0
: bssn_cuda_unpack_state_segments_from_device_buffer(
block, state_count, data, block->shape, segment_count, meta.data()) == 0;
#else
(void)data; (void)state_count; (void)dir; (void)type; (void)vars; (void)segment_count;
return false;
#endif
}
int cuda_data_packer_device_batched(double *data,
@@ -971,11 +1085,6 @@ int cuda_data_packer_device_batched(double *data,
const int state_count = cuda_state_var_count(VarLists, VarListd);
if (!cuda_device_state_count_supported(state_count))
return -1;
#if USE_CUDA_Z4C && (ABEtype == 2)
if (state_count == Z4C_CUDA_STATE_COUNT)
return -1;
#endif
int size_out = 0;
Block *batch_block = 0;
int batch_type = 0;
@@ -1240,7 +1349,7 @@ int data_packer_with_device_buffer(double *data,
MyList<var> *VarListd,
int Symmetry)
{
#if USE_CUDA_BSSN
#if USE_CUDA_BSSN || USE_CUDA_Z4C
const double batched_t0 = sync_profile_enabled() ? MPI_Wtime() : 0.0;
const int batched = cuda_data_packer_device_batched(data, src, dst, rank_in, dir,
VarLists, VarListd, Symmetry);
@@ -5063,20 +5172,37 @@ int Parallel::data_packer(double *data, MyList<Parallel::gridseg> *src, MyList<P
}
#endif
#endif
#if USE_CUDA_BSSN
if (dir == PACK && state_idx == 0 && cuda_state_count_direct_supported(state_count) &&
src->data && src->data->Bg && bssn_cuda_has_resident_state(src->data->Bg))
{
if (!cuda_download_resident_subset_to_host(src->data->Bg, VarLists, state_count))
#if USE_CUDA_BSSN || USE_CUDA_Z4C
if (dir == PACK && state_idx == 0 && cuda_state_count_direct_supported(state_count) &&
src->data && src->data->Bg)
{
if (!cuda_download_resident_subset_to_host(src->data->Bg, VarLists, state_count))
{
cout << "Parallel::data_packer: CUDA resident fallback download failed." << endl;
MPI_Abort(MPI_COMM_WORLD, 1);
}
}
#endif
if (dir == PACK)
switch (type)
{
if (dir == PACK)
{
if (!src->data || !src->data->Bg || !src->data->Bg->fgfs ||
!varls || !varls->data ||
!src->data->Bg->fgfs[varls->data->sgfn])
{
fprintf(stderr,
"Parallel::data_packer: null host pack source "
"state_count=%d state_idx=%d type=%d rank_in=%d "
"var=%s sgfn=%d src_data=%p src_bg=%p fgfs=%p\n",
state_count, state_idx, type, rank_in,
(varls && varls->data) ? varls->data->name : "(null)",
(varls && varls->data) ? varls->data->sgfn : -1,
(void *)src->data,
(src->data ? (void *)src->data->Bg : 0),
(src->data && src->data->Bg ? (void *)src->data->Bg->fgfs : 0));
MPI_Abort(MPI_COMM_WORLD, 1);
}
switch (type)
{
// attention must be paied to the difference between src's llb,uub and dst's llb,uub
case 1:
f_copy(DIM, dst->data->llb, dst->data->uub, dst->data->shape, data + size_out,
@@ -5088,20 +5214,21 @@ int Parallel::data_packer(double *data, MyList<Parallel::gridseg> *src, MyList<P
src->data->Bg->bbox, src->data->Bg->bbox + dim, src->data->Bg->shape, src->data->Bg->fgfs[varls->data->sgfn],
dst->data->llb, dst->data->uub, varls->data->SoA, Symmetry);
break;
case 3:
f_prolong3(DIM, src->data->Bg->bbox, src->data->Bg->bbox + dim, src->data->Bg->shape, src->data->Bg->fgfs[varls->data->sgfn],
dst->data->llb, dst->data->uub, dst->data->shape, data + size_out,
dst->data->llb, dst->data->uub, varls->data->SoA, Symmetry);
}
case 3:
f_prolong3(DIM, src->data->Bg->bbox, src->data->Bg->bbox + dim, src->data->Bg->shape, src->data->Bg->fgfs[varls->data->sgfn],
dst->data->llb, dst->data->uub, dst->data->shape, data + size_out,
dst->data->llb, dst->data->uub, varls->data->SoA, Symmetry);
}
}
if (dir == UNPACK) // from target data to corresponding grid
{
f_copy(DIM, dst->data->Bg->bbox, dst->data->Bg->bbox + dim, dst->data->Bg->shape, dst->data->Bg->fgfs[varld->data->sgfn],
dst->data->llb, dst->data->uub, dst->data->shape, data + size_out,
dst->data->llb, dst->data->uub);
#if USE_CUDA_BSSN
if (cuda_state_count_direct_supported(state_count) &&
dst->data && dst->data->Bg && bssn_cuda_has_resident_state(dst->data->Bg))
{
#if USE_CUDA_BSSN || USE_CUDA_Z4C
if (cuda_state_count_direct_supported(state_count) &&
dst->data && dst->data->Bg)
{
if (!cuda_unpack_host_region_to_resident(dst->data->Bg, state_idx, data + size_out, dst->data))
{
cout << "Parallel::data_packer: CUDA resident fallback upload failed." << endl;