Skip to content

Commit f009e52

Browse files
authored
Merge pull request #1672 from CEED/jeremy/work-vector
ceed - add Ceed[Get,Restore]WorkVector
2 parents 3156c35 + 73501bf commit f009e52

File tree

4 files changed

+175
-7
lines changed

4 files changed

+175
-7
lines changed

include/ceed-impl.h

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@ typedef struct {
8282
Ceed delegate;
8383
} ObjDelegate;
8484

85+
// Work vector tracking
86+
typedef struct CeedWorkVectors_private *CeedWorkVectors;
87+
struct CeedWorkVectors_private {
88+
CeedInt num_vecs, max_vecs;
89+
bool *is_in_use;
90+
CeedVector *vecs;
91+
};
92+
8593
struct Ceed_private {
8694
const char *resource;
8795
Ceed delegate;
@@ -113,13 +121,14 @@ struct Ceed_private {
113121
int (*OperatorCreate)(CeedOperator);
114122
int (*OperatorCreateAtPoints)(CeedOperator);
115123
int (*CompositeOperatorCreate)(CeedOperator);
116-
int ref_count;
117-
void *data;
118-
bool is_debug;
119-
bool has_valid_op_fallback_resource;
120-
bool is_deterministic;
121-
char err_msg[CEED_MAX_RESOURCE_LEN];
122-
FOffset *f_offsets;
124+
int ref_count;
125+
void *data;
126+
bool is_debug;
127+
bool has_valid_op_fallback_resource;
128+
bool is_deterministic;
129+
char err_msg[CEED_MAX_RESOURCE_LEN];
130+
FOffset *f_offsets;
131+
CeedWorkVectors work_vectors;
123132
};
124133

125134
struct CeedVector_private {

include/ceed/backend.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,8 @@ CEED_EXTERN int CeedSetBackendFunctionImpl(Ceed ceed, const char *type, void *ob
252252
CEED_EXTERN int CeedGetData(Ceed ceed, void *data);
253253
CEED_EXTERN int CeedSetData(Ceed ceed, void *data);
254254
CEED_EXTERN int CeedReference(Ceed ceed);
255+
CEED_EXTERN int CeedGetWorkVector(Ceed ceed, CeedSize len, CeedVector *vec);
256+
CEED_EXTERN int CeedRestoreWorkVector(Ceed ceed, CeedVector *vec);
255257

256258
CEED_EXTERN int CeedVectorHasValidArray(CeedVector vec, bool *has_valid_array);
257259
CEED_EXTERN int CeedVectorHasBorrowedArrayOfType(CeedVector vec, CeedMemType mem_type, bool *has_borrowed_array_of_type);

interface/ceed.c

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,43 @@ int CeedRegisterImpl(const char *prefix, int (*init)(const char *, Ceed), unsign
138138
return CEED_ERROR_SUCCESS;
139139
}
140140

141+
/**
142+
@brief Create a work vector space for a `ceed`
143+
144+
@param[in,out] ceed `Ceed` to create work vector space for
145+
146+
@return An error code: 0 - success, otherwise - failure
147+
148+
@ref Developer
149+
**/
150+
static int CeedWorkVectorsCreate(Ceed ceed) {
151+
CeedCall(CeedCalloc(1, &ceed->work_vectors));
152+
return CEED_ERROR_SUCCESS;
153+
}
154+
155+
/**
156+
@brief Destroy a work vector space for a `ceed`
157+
158+
@param[in,out] ceed `Ceed` to destroy work vector space for
159+
160+
@return An error code: 0 - success, otherwise - failure
161+
162+
@ref Developer
163+
**/
164+
static int CeedWorkVectorsDestroy(Ceed ceed) {
165+
if (!ceed->work_vectors) return CEED_ERROR_SUCCESS;
166+
for (CeedSize i = 0; i < ceed->work_vectors->num_vecs; i++) {
167+
CeedCheck(!ceed->work_vectors->is_in_use[i], ceed, CEED_ERROR_ACCESS, "Work vector %" CeedSize_FMT " checked out but not returned");
168+
ceed->ref_count += 2; // Note: increase ref_count to prevent Ceed destructor from triggering again
169+
CeedCall(CeedVectorDestroy(&ceed->work_vectors->vecs[i]));
170+
ceed->ref_count -= 1; // Note: restore ref_count
171+
}
172+
CeedCall(CeedFree(&ceed->work_vectors->is_in_use));
173+
CeedCall(CeedFree(&ceed->work_vectors->vecs));
174+
CeedCall(CeedFree(&ceed->work_vectors));
175+
return CEED_ERROR_SUCCESS;
176+
}
177+
141178
/// @}
142179

143180
/// ----------------------------------------------------------------------------
@@ -751,6 +788,81 @@ int CeedReference(Ceed ceed) {
751788
return CEED_ERROR_SUCCESS;
752789
}
753790

791+
/**
792+
@brief Get a `CeedVector` for scratch work from a `Ceed` context.
793+
794+
Note: This vector must be restored with @ref CeedRestoreWorkVector().
795+
796+
@param[in] ceed `Ceed` context
797+
@param[in] len Minimum length of work vector
798+
@param[out] vec Address of the variable where `CeedVector` will be stored
799+
800+
@return An error code: 0 - success, otherwise - failure
801+
802+
@ref Backend
803+
**/
804+
int CeedGetWorkVector(Ceed ceed, CeedSize len, CeedVector *vec) {
805+
CeedInt i = 0;
806+
807+
if (!ceed->work_vectors) CeedCall(CeedWorkVectorsCreate(ceed));
808+
809+
// Search for big enough work vector
810+
for (i = 0; i < ceed->work_vectors->num_vecs; i++) {
811+
if (!ceed->work_vectors->is_in_use[i]) {
812+
CeedSize work_len;
813+
814+
CeedCall(CeedVectorGetLength(ceed->work_vectors->vecs[i], &work_len));
815+
if (work_len >= len) break;
816+
}
817+
}
818+
// Long enough vector was not found
819+
if (i == ceed->work_vectors->num_vecs) {
820+
if (ceed->work_vectors->max_vecs == 0) {
821+
ceed->work_vectors->max_vecs = 1;
822+
CeedCall(CeedCalloc(ceed->work_vectors->max_vecs, &ceed->work_vectors->vecs));
823+
CeedCall(CeedCalloc(ceed->work_vectors->max_vecs, &ceed->work_vectors->is_in_use));
824+
} else if (ceed->work_vectors->max_vecs == i) {
825+
ceed->work_vectors->max_vecs *= 2;
826+
CeedCall(CeedRealloc(ceed->work_vectors->max_vecs, &ceed->work_vectors->vecs));
827+
CeedCall(CeedRealloc(ceed->work_vectors->max_vecs, &ceed->work_vectors->is_in_use));
828+
}
829+
ceed->work_vectors->num_vecs++;
830+
CeedCallBackend(CeedVectorCreate(ceed, len, &ceed->work_vectors->vecs[i]));
831+
ceed->ref_count--; // Note: ref_count manipulation to prevent a ref-loop
832+
}
833+
// Return pointer to work vector
834+
ceed->work_vectors->is_in_use[i] = true;
835+
*vec = NULL;
836+
CeedCall(CeedVectorReferenceCopy(ceed->work_vectors->vecs[i], vec));
837+
ceed->ref_count++; // Note: bump ref_count to account for external access
838+
return CEED_ERROR_SUCCESS;
839+
}
840+
841+
/**
842+
@brief Restore a `CeedVector` for scratch work from a `Ceed` context from @ref CeedGetWorkVector()
843+
844+
@param[in] ceed `Ceed` context
845+
@param[out] vec `CeedVector` to restore
846+
847+
@return An error code: 0 - success, otherwise - failure
848+
849+
@ref Backend
850+
**/
851+
int CeedRestoreWorkVector(Ceed ceed, CeedVector *vec) {
852+
for (CeedInt i = 0; i < ceed->work_vectors->num_vecs; i++) {
853+
if (*vec == ceed->work_vectors->vecs[i]) {
854+
CeedCheck(ceed->work_vectors->is_in_use[i], ceed, CEED_ERROR_ACCESS, "Work vector %" CeedSize_FMT " was not checked out but is being returned");
855+
CeedCall(CeedVectorDestroy(vec));
856+
ceed->work_vectors->is_in_use[i] = false;
857+
ceed->ref_count--; // Note: reduce ref_count again to prevent a ref-loop
858+
return CEED_ERROR_SUCCESS;
859+
}
860+
}
861+
// LCOV_EXCL_START
862+
return CeedError(ceed, CEED_ERROR_MAJOR, "vec was not checked out via CeedGetWorkVector()");
863+
// LCOV_EXCL_STOP
864+
}
865+
754866
/// @}
755867

756868
/// ----------------------------------------------------------------------------
@@ -1200,6 +1312,7 @@ int CeedDestroy(Ceed *ceed) {
12001312
CeedCall(CeedFree(&(*ceed)->resource));
12011313
CeedCall(CeedDestroy(&(*ceed)->op_fallback_ceed));
12021314
CeedCall(CeedFree(&(*ceed)->op_fallback_resource));
1315+
CeedCall(CeedWorkVectorsDestroy(*ceed));
12031316
CeedCall(CeedFree(ceed));
12041317
return CEED_ERROR_SUCCESS;
12051318
}

tests/t130-vector.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/// @file
2+
/// Test getting and restoring work vectors
3+
/// \test Test getting and restoring work vectors
4+
5+
#include <ceed.h>
6+
#include <ceed/backend.h>
7+
#include <stdio.h>
8+
9+
int main(int argc, char **argv) {
10+
Ceed ceed;
11+
12+
CeedInit(argv[1], &ceed);
13+
14+
// Check for getting the same work vector back
15+
{
16+
CeedVector x, y;
17+
18+
CeedGetWorkVector(ceed, 20, &x);
19+
// Do not do this!
20+
CeedVector x_copy = x;
21+
22+
CeedRestoreWorkVector(ceed, &x);
23+
CeedGetWorkVector(ceed, 20, &y);
24+
if (y != x_copy) printf("failed to return same work vector");
25+
CeedRestoreWorkVector(ceed, &y);
26+
}
27+
28+
// Check for getting a new work vector back
29+
{
30+
CeedVector x, y;
31+
32+
CeedGetWorkVector(ceed, 20, &x);
33+
// Do not do this!
34+
CeedVector x_copy = x;
35+
36+
CeedRestoreWorkVector(ceed, &x);
37+
CeedGetWorkVector(ceed, 30, &y);
38+
if (y == x_copy) printf("failed to return new work vector");
39+
CeedRestoreWorkVector(ceed, &y);
40+
}
41+
42+
CeedDestroy(&ceed);
43+
return 0;
44+
}

0 commit comments

Comments
 (0)