1 // Copyright (c) 2017-2022, Lawrence Livermore National Security, LLC and other CEED contributors. 2 // All Rights Reserved. See the top-level LICENSE and NOTICE files for details. 3 // 4 // SPDX-License-Identifier: BSD-2-Clause 5 // 6 // This file is part of CEED: http://github.com/ceed 7 8 #include <ceed.h> 9 #include <ceed/backend.h> 10 #include <math.h> 11 #include <stdio.h> 12 #include <valgrind/memcheck.h> 13 14 #include "ceed-memcheck.h" 15 16 //------------------------------------------------------------------------------ 17 // QFunction Apply 18 //------------------------------------------------------------------------------ 19 static int CeedQFunctionApply_Memcheck(CeedQFunction qf, CeedInt Q, CeedVector *U, CeedVector *V) { 20 Ceed ceed; 21 void *ctx_data = NULL; 22 CeedInt num_in, num_out; 23 CeedQFunctionUser f = NULL; 24 CeedQFunctionField *output_fields; 25 CeedQFunction_Memcheck *impl; 26 27 CeedCallBackend(CeedQFunctionGetCeed(qf, &ceed)); 28 CeedCallBackend(CeedQFunctionGetData(qf, &impl)); 29 CeedCallBackend(CeedQFunctionGetContextData(qf, CEED_MEM_HOST, &ctx_data)); 30 CeedCallBackend(CeedQFunctionGetUserFunction(qf, &f)); 31 CeedCallBackend(CeedQFunctionGetNumArgs(qf, &num_in, &num_out)); 32 int mem_block_ids[num_out]; 33 34 // Get input/output arrays 35 for (CeedInt i = 0; i < num_in; i++) { 36 CeedCallBackend(CeedVectorGetArrayRead(U[i], CEED_MEM_HOST, &impl->inputs[i])); 37 } 38 for (CeedInt i = 0; i < num_out; i++) { 39 CeedSize len; 40 char name[32] = ""; 41 42 CeedCallBackend(CeedVectorGetArrayWrite(V[i], CEED_MEM_HOST, &impl->outputs[i])); 43 44 CeedCallBackend(CeedVectorGetLength(V[i], &len)); 45 VALGRIND_MAKE_MEM_UNDEFINED(impl->outputs[i], len); 46 47 snprintf(name, 32, "'QFunction output %" CeedInt_FMT "'", i); 48 mem_block_ids[i] = VALGRIND_CREATE_BLOCK(impl->outputs[i], len, name); 49 } 50 51 // Call user function 52 CeedCallBackend(f(ctx_data, Q, impl->inputs, impl->outputs)); 53 54 // Restore input arrays 55 for (CeedInt i = 0; i < num_in; i++) { 56 CeedCallBackend(CeedVectorRestoreArrayRead(U[i], &impl->inputs[i])); 57 } 58 // Check for unset output values 59 { 60 const char *kernel_name; 61 char *kernel_path; 62 63 CeedCallBackend(CeedQFunctionGetSourcePath(qf, &kernel_path)); 64 CeedCallBackend(CeedQFunctionGetKernelName(qf, &kernel_name)); 65 CeedCallBackend(CeedQFunctionGetFields(qf, NULL, NULL, NULL, &output_fields)); 66 for (CeedInt i = 0; i < num_out; i++) { 67 CeedInt field_size; 68 69 // Note: need field size because vector may be longer than needed for output 70 CeedCallBackend(CeedQFunctionFieldGetSize(output_fields[i], &field_size)); 71 for (CeedSize j = 0; j < field_size * (CeedSize)Q; j++) { 72 CeedCheck(!isnan(impl->outputs[i][j]), ceed, CEED_ERROR_BACKEND, 73 "QFunction output %" CeedInt_FMT " entry %" CeedSize_FMT " is NaN after restoring write-only access: %s:%s ", i, j, kernel_path, 74 kernel_name); 75 } 76 CeedCallBackend(CeedVectorRestoreArray(V[i], &impl->outputs[i])); 77 VALGRIND_DISCARD(mem_block_ids[i]); 78 } 79 } 80 CeedCallBackend(CeedQFunctionRestoreContextData(qf, &ctx_data)); 81 return CEED_ERROR_SUCCESS; 82 } 83 84 //------------------------------------------------------------------------------ 85 // QFunction Destroy 86 //------------------------------------------------------------------------------ 87 static int CeedQFunctionDestroy_Memcheck(CeedQFunction qf) { 88 CeedQFunction_Memcheck *impl; 89 90 CeedCallBackend(CeedQFunctionGetData(qf, (void *)&impl)); 91 CeedCallBackend(CeedFree(&impl->inputs)); 92 CeedCallBackend(CeedFree(&impl->outputs)); 93 CeedCallBackend(CeedFree(&impl)); 94 return CEED_ERROR_SUCCESS; 95 } 96 97 //------------------------------------------------------------------------------ 98 // QFunction Create 99 //------------------------------------------------------------------------------ 100 int CeedQFunctionCreate_Memcheck(CeedQFunction qf) { 101 Ceed ceed; 102 CeedQFunction_Memcheck *impl; 103 104 CeedCallBackend(CeedQFunctionGetCeed(qf, &ceed)); 105 CeedCallBackend(CeedCalloc(1, &impl)); 106 CeedCallBackend(CeedCalloc(CEED_FIELD_MAX, &impl->inputs)); 107 CeedCallBackend(CeedCalloc(CEED_FIELD_MAX, &impl->outputs)); 108 CeedCallBackend(CeedQFunctionSetData(qf, impl)); 109 CeedCallBackend(CeedSetBackendFunction(ceed, "QFunction", qf, "Apply", CeedQFunctionApply_Memcheck)); 110 CeedCallBackend(CeedSetBackendFunction(ceed, "QFunction", qf, "Destroy", CeedQFunctionDestroy_Memcheck)); 111 return CEED_ERROR_SUCCESS; 112 } 113 114 //------------------------------------------------------------------------------ 115