Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove manual memory management in LB code #4108

Merged
merged 17 commits into from
Jan 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 61 additions & 109 deletions src/core/grid_based_algorithms/halo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,91 +33,43 @@
#include "halo.hpp"

#include <utils/Vector.hpp>
#include <utils/memory.hpp>

#include <cstdlib>
#include <cstring>
#include <memory>

/** Primitive fieldtypes and their initializers */
struct _Fieldtype fieldtype_double = {0, nullptr, nullptr, sizeof(double), 0,
0, 0, false, nullptr};

void halo_create_field_vector(int vblocks, int vstride, int vskip,
Fieldtype oldtype, Fieldtype *const newtype) {

Fieldtype ntype = *newtype = (Fieldtype)Utils::malloc(sizeof(*ntype));

ntype->subtype = oldtype;
ntype->vflag = true;

ntype->vblocks = vblocks;
ntype->vstride = vstride;
ntype->vskip = vskip;

ntype->extent = oldtype->extent * ((vblocks - 1) * vskip + vstride);

int count = ntype->count = oldtype->count;
ntype->lengths = (int *)Utils::malloc(count * 2 * sizeof(int));
ntype->disps = (int *)((char *)ntype->lengths + count * sizeof(int));

for (int i = 0; i < count; i++) {
ntype->disps[i] = oldtype->disps[i];
ntype->lengths[i] = oldtype->lengths[i];
}
}

void halo_create_field_hvector(int vblocks, int vstride, int vskip,
Fieldtype oldtype, Fieldtype *const newtype) {

Fieldtype ntype = *newtype = (Fieldtype)Utils::malloc(sizeof(*ntype));

ntype->subtype = oldtype;
ntype->vflag = false;

ntype->vblocks = vblocks;
ntype->vstride = vstride;
ntype->vskip = vskip;

ntype->extent = oldtype->extent * vstride + (vblocks - 1) * vskip;

int const count = ntype->count = oldtype->count;
ntype->lengths = (int *)Utils::malloc(count * 2 * sizeof(int));
ntype->disps = (int *)((char *)ntype->lengths + count * sizeof(int));

for (int i = 0; i < count; i++) {
ntype->disps[i] = oldtype->disps[i];
ntype->lengths[i] = oldtype->lengths[i];
}
}
/** Predefined fieldtype for double-precision LB */
static std::shared_ptr<FieldType> fieldtype_double =
std::make_shared<FieldType>(static_cast<int>(sizeof(double)));

/** Set halo region to a given value
* @param[out] dest pointer to the halo buffer
* @param value integer value to write into the halo buffer
* @param type halo field layout description
*/
void halo_dtset(char *dest, int value, Fieldtype type) {
void halo_dtset(char *dest, int value, std::shared_ptr<FieldType> type) {
auto const vblocks = type->vblocks;
auto const vstride = type->vstride;
auto const vskip = type->vskip;
auto const count = type->count;
int const *const lens = type->lengths;
int const *const disps = type->disps;
auto const &lens = type->lengths;
auto const &disps = type->disps;
auto const extent = type->extent;
auto const block_size = static_cast<long>(vskip) * static_cast<long>(extent);

for (int i = 0; i < vblocks; i++) {
for (int j = 0; j < vstride; j++) {
for (int k = 0; k < count; k++)
for (std::size_t k = 0; k < disps.size(); k++)
memset(dest + disps[k], value, lens[k]);
}
dest += block_size;
}
}

void halo_dtcopy(char *r_buffer, char *s_buffer, int count, Fieldtype type);
void halo_dtcopy(char *r_buffer, char *s_buffer, int count,
std::shared_ptr<FieldType> type);

void halo_copy_vector(char *r_buffer, char *s_buffer, int count, Fieldtype type,
bool vflag) {
void halo_copy_vector(char *r_buffer, char *s_buffer, int count,
std::shared_ptr<FieldType> type, bool vflag) {

auto const vblocks = type->vblocks;
auto const vstride = type->vstride;
Expand All @@ -136,13 +88,14 @@ void halo_copy_vector(char *r_buffer, char *s_buffer, int count, Fieldtype type,
}
}

/** Copy lattice data with layout described by fieldtype.
/** Copy lattice data with layout described by @p type.
* @param r_buffer data destination
* @param s_buffer data source
* @param count amount of data to copy
* @param type field layout type
*/
void halo_dtcopy(char *r_buffer, char *s_buffer, int count, Fieldtype type) {
void halo_dtcopy(char *r_buffer, char *s_buffer, int count,
std::shared_ptr<FieldType> type) {

if (type->subtype) {
halo_copy_vector(r_buffer, s_buffer, count, type, type->vflag);
Expand All @@ -162,31 +115,30 @@ void halo_dtcopy(char *r_buffer, char *s_buffer, int count, Fieldtype type) {
}
}

void prepare_halo_communication(HaloCommunicator *const hc,
Lattice const *const lattice,
Fieldtype fieldtype, MPI_Datatype datatype,
void prepare_halo_communication(HaloCommunicator &hc, const Lattice &lattice,
MPI_Datatype datatype,
const Utils::Vector3i &local_node_grid) {

const auto grid = lattice->grid;
const auto period = lattice->halo_grid;
const auto &grid = lattice.grid;
const auto &period = lattice.halo_grid;

for (int n = 0; n < hc->num; n++) {
MPI_Type_free(&(hc->halo_info[n].datatype));
for (int n = 0; n < hc.num; n++) {
MPI_Type_free(&(hc.halo_info[n].datatype));
}

int const num = 2 * 3; /* two communications in each space direction */
hc->num = num;
hc->halo_info.resize(num);
hc.num = num;
hc.halo_info.resize(num);

auto const extent = static_cast<long>(fieldtype->extent);
auto const extent = static_cast<long>(fieldtype_double->extent);

auto const node_neighbors = calc_node_neighbors(comm_cart);

int cnt = 0;
for (int dir = 0; dir < 3; dir++) {
for (int lr = 0; lr < 2; lr++) {

HaloInfo *hinfo = &(hc->halo_info[cnt]);
HaloInfo &hinfo = hc.halo_info[cnt];

int nblocks = 1;
for (int k = dir + 1; k < 3; k++) {
Expand All @@ -203,107 +155,107 @@ void prepare_halo_communication(HaloCommunicator *const hc,

if (lr == 0) {
/* send to left, recv from right */
hinfo->s_offset = extent * static_cast<long>(stride * 1);
hinfo->r_offset = extent * static_cast<long>(stride * (grid[dir] + 1));
hinfo.s_offset = extent * static_cast<long>(stride * 1);
hinfo.r_offset = extent * static_cast<long>(stride * (grid[dir] + 1));
} else {
/* send to right, recv from left */
hinfo->s_offset = extent * static_cast<long>(stride * grid[dir]);
hinfo->r_offset = extent * static_cast<long>(stride * 0);
hinfo.s_offset = extent * static_cast<long>(stride * grid[dir]);
hinfo.r_offset = extent * static_cast<long>(stride * 0);
}

hinfo->source_node = node_neighbors[2 * dir + 1 - lr];
hinfo->dest_node = node_neighbors[2 * dir + lr];
hinfo.source_node = node_neighbors[2 * dir + 1 - lr];
hinfo.dest_node = node_neighbors[2 * dir + lr];

halo_create_field_vector(nblocks, stride, skip, fieldtype,
&hinfo->fieldtype);
hinfo.fieldtype = std::make_shared<FieldType>(nblocks, stride, skip, true,
fieldtype_double);

MPI_Type_vector(nblocks, stride, skip, datatype, &hinfo->datatype);
MPI_Type_commit(&hinfo->datatype);
MPI_Type_vector(nblocks, stride, skip, datatype, &hinfo.datatype);
MPI_Type_commit(&hinfo.datatype);

if (!box_geo.periodic(dir) &&
(local_geo.boundary()[2 * dir + lr] != 0 ||
local_geo.boundary()[2 * dir + 1 - lr] != 0)) {
if (local_node_grid[dir] == 1) {
hinfo->type = HALO_OPEN;
hinfo.type = HALO_OPEN;
} else if (lr == 0) {
if (local_geo.boundary()[2 * dir + lr] == 1) {
hinfo->type = HALO_RECV;
hinfo.type = HALO_RECV;
} else {
hinfo->type = HALO_SEND;
hinfo.type = HALO_SEND;
}
} else {
if (local_geo.boundary()[2 * dir + lr] == -1) {
hinfo->type = HALO_RECV;
hinfo.type = HALO_RECV;
} else {
hinfo->type = HALO_SEND;
hinfo.type = HALO_SEND;
}
}
} else {
if (local_node_grid[dir] == 1) {
hc->halo_info[cnt].type = HALO_LOCL;
hc.halo_info[cnt].type = HALO_LOCL;
} else {
hc->halo_info[cnt].type = HALO_SENDRECV;
hc.halo_info[cnt].type = HALO_SENDRECV;
}
}
cnt++;
}
}
}

void release_halo_communication(HaloCommunicator *const hc) {
for (int n = 0; n < hc->num; n++) {
MPI_Type_free(&(hc->halo_info[n].datatype));
void release_halo_communication(HaloCommunicator &hc) {
for (int n = 0; n < hc.num; n++) {
MPI_Type_free(&(hc.halo_info[n].datatype));
}
}

void halo_communication(HaloCommunicator const *const hc, char *const base) {
void halo_communication(const HaloCommunicator &hc, char *const base) {

Fieldtype fieldtype;
std::shared_ptr<FieldType> fieldtype;
MPI_Datatype datatype;
MPI_Request request;
MPI_Status status;

for (int n = 0; n < hc->num; n++) {
for (int n = 0; n < hc.num; n++) {
int s_node, r_node;
int comm_type = hc->halo_info[n].type;
char *s_buffer = (char *)base + hc->halo_info[n].s_offset;
char *r_buffer = (char *)base + hc->halo_info[n].r_offset;
int comm_type = hc.halo_info[n].type;
char *s_buffer = (char *)base + hc.halo_info[n].s_offset;
char *r_buffer = (char *)base + hc.halo_info[n].r_offset;

switch (comm_type) {

case HALO_LOCL:
fieldtype = hc->halo_info[n].fieldtype;
fieldtype = hc.halo_info[n].fieldtype;
halo_dtcopy(r_buffer, s_buffer, 1, fieldtype);
break;

case HALO_SENDRECV:
datatype = hc->halo_info[n].datatype;
s_node = hc->halo_info[n].source_node;
r_node = hc->halo_info[n].dest_node;
datatype = hc.halo_info[n].datatype;
s_node = hc.halo_info[n].source_node;
r_node = hc.halo_info[n].dest_node;
MPI_Sendrecv(s_buffer, 1, datatype, r_node, REQ_HALO_SPREAD, r_buffer, 1,
datatype, s_node, REQ_HALO_SPREAD, comm_cart, &status);
break;

case HALO_SEND:
datatype = hc->halo_info[n].datatype;
fieldtype = hc->halo_info[n].fieldtype;
r_node = hc->halo_info[n].dest_node;
datatype = hc.halo_info[n].datatype;
fieldtype = hc.halo_info[n].fieldtype;
r_node = hc.halo_info[n].dest_node;
MPI_Isend(s_buffer, 1, datatype, r_node, REQ_HALO_SPREAD, comm_cart,
&request);
halo_dtset(r_buffer, 0, fieldtype);
MPI_Wait(&request, &status);
break;

case HALO_RECV:
datatype = hc->halo_info[n].datatype;
s_node = hc->halo_info[n].source_node;
datatype = hc.halo_info[n].datatype;
s_node = hc.halo_info[n].source_node;
MPI_Irecv(r_buffer, 1, datatype, s_node, REQ_HALO_SPREAD, comm_cart,
&request);
MPI_Wait(&request, &status);
break;

case HALO_OPEN:
fieldtype = hc->halo_info[n].fieldtype;
fieldtype = hc.halo_info[n].fieldtype;
/** \todo this does not work for the n_i - \<n_i\> */
halo_dtset(r_buffer, 0, fieldtype);
break;
Expand Down
Loading