HPCToolkit
main.cpp
Go to the documentation of this file.
1 // -*-Mode: C++;-*-
2 
3 // * BeginRiceCopyright *****************************************************
4 //
5 // $HeadURL$
6 // $Id$
7 //
8 // --------------------------------------------------------------------------
9 // Part of HPCToolkit (hpctoolkit.org)
10 //
11 // Information about sources of support for research and development of
12 // HPCToolkit is at 'hpctoolkit.org' and in 'README.Acknowledgments'.
13 // --------------------------------------------------------------------------
14 //
15 // Copyright ((c)) 2002-2019, Rice University
16 // All rights reserved.
17 //
18 // Redistribution and use in source and binary forms, with or without
19 // modification, are permitted provided that the following conditions are
20 // met:
21 //
22 // * Redistributions of source code must retain the above copyright
23 // notice, this list of conditions and the following disclaimer.
24 //
25 // * Redistributions in binary form must reproduce the above copyright
26 // notice, this list of conditions and the following disclaimer in the
27 // documentation and/or other materials provided with the distribution.
28 //
29 // * Neither the name of Rice University (RICE) nor the names of its
30 // contributors may be used to endorse or promote products derived from
31 // this software without specific prior written permission.
32 //
33 // This software is provided by RICE and contributors "as is" and any
34 // express or implied warranties, including, but not limited to, the
35 // implied warranties of merchantability and fitness for a particular
36 // purpose are disclaimed. In no event shall RICE or contributors be
37 // liable for any direct, indirect, incidental, special, exemplary, or
38 // consequential damages (including, but not limited to, procurement of
39 // substitute goods or services; loss of use, data, or profits; or
40 // business interruption) however caused and on any theory of liability,
41 // whether in contract, strict liability, or tort (including negligence
42 // or otherwise) arising in any way out of the use of this software, even
43 // if advised of the possibility of such damage.
44 //
45 // ******************************************************* EndRiceCopyright *
46 
47 //***************************************************************************
48 //
49 // File:
50 // $HeadURL$
51 //
52 // Purpose:
53 // [The purpose of this file]
54 //
55 // Description:
56 // [The set of functions, macros, etc. defined in the file]
57 //
58 //***************************************************************************
59 
60 //**************************** MPI Include Files ****************************
61 
62 #include <mpi.h>
63 
64 //************************* System Include Files ****************************
65 
66 #include <iostream>
67 #include <fstream>
68 #include <typeinfo>
69 #include <signal.h>
70 #include <unistd.h>
71 
72 #include <string>
73 using std::string;
74 
75 #include <vector>
76 using std::vector;
77 
78 #include <cstdlib> // getenv()
79 #include <cmath> // ceil()
80 #include <climits> // UCHAR_MAX, PATH_MAX
81 #include <cctype> // isdigit()
82 #include <cstring> // strcpy()
83 
84 //*************************** User Include Files ****************************
85 
86 #include <include/uint.h>
87 
88 #include "Args.hpp"
89 #include "ParallelAnalysis.hpp"
90 
92 #include <lib/analysis/Util.hpp>
93 
95 #include <lib/prof/FileError.hpp>
96 
98 
100 #include <lib/support/FileUtil.hpp>
101 #include <lib/support/Logic.hpp>
103 #include <lib/support/StrUtil.hpp>
104 
105 #define DBG_PROF_MPI 0
106 
107 //*************************** Forward Declarations ***************************
108 
109 static int
110 realmain(int argc, char* const* argv);
111 
114  vector<uint>& groupIdToGroupSizeMap,
115  int myRank, int numRanks);
116 
117 
118 static void
120  const Analysis::Args& args,
122  const vector<uint>& groupIdToGroupSizeMap,
123  int myRank, int numRanks);
124 
125 static void
127  const Analysis::Args& args,
129  const vector<uint>& groupIdToGroupSizeMap,
130  int myRank, int numRanks);
131 
132 static uint
134  const Analysis::Args& args,
135  uint& mDrvdBeg, uint& mDrvdEnd,
136  uint& mXDrvdBeg, uint& mXDrvdEnd,
137  vector<VMAIntervalSet*>& groupIdToGroupMetricsMap,
138  const vector<uint>& groupIdToGroupSizeMap,
139  int myRank);
140 
141 static void
143  const string& profileFile,
144  const Analysis::Args& args, uint groupId, uint groupMax,
145  vector<VMAIntervalSet*>& groupIdToGroupMetricsMap,
146  int myRank);
147 
148 static void
150  const string& profileFile,
151  const Analysis::Args& args, uint groupId, uint groupMax,
152  int myRank);
153 
154 static string
155 makeDBFileName(const string& dbDir, uint groupId, const string& profileFile);
156 
157 static void
158 writeMetricsDB(Prof::CallPath::Profile& profGbl, uint mBegId, uint mEndId,
159  const string& metricDBFnm);
160 
161 
162 static void
163 writeStructure(const Prof::Struct::Tree& structure, const char* baseNm,
164  int myRank) __attribute__((unused));
165 
166 static void
167 writeProfile(const Prof::CallPath::Profile& prof, const char* baseNm,
168  int myRank) __attribute__((unused));
169 
170 static std::string
171 makeFileName(const char* baseNm, const char* ext, int myRank);
172 
173 
174 //****************************************************************************
175 
176 void
178 (
179  int error_code
180 )
181 {
182  MPI_Abort(MPI_COMM_WORLD, error_code);
183 }
184 
185 
186 int
187 main(int argc, char* const* argv)
188 {
189  int ret;
190 
191  try {
192  ret = realmain(argc, argv);
193  }
194  catch (const Diagnostics::Exception& x) {
195  DIAG_EMsg(x.message());
196  exit(1);
197  }
198  catch (const std::bad_alloc& x) {
199  DIAG_EMsg("[std::bad_alloc] " << x.what());
200  exit(1);
201  }
202  catch (const std::exception& x) {
203  DIAG_EMsg("[std::exception] " << x.what());
204  exit(1);
205  }
206  catch (...) {
207  DIAG_EMsg("Unknown exception encountered!");
208  exit(2);
209  }
210 
211  return ret;
212 }
213 
214 
215 static void
216 abort_timeout_handler(int sig, siginfo_t* siginfo, void* context)
217 {
218  abort();
219 }
220 
221 static void
223 {
224  char *error_timeout = getenv("HPCPROF_ABORT_TIMEOUT");
225  if (error_timeout) {
226  int seconds = atoi(error_timeout);
227  if (seconds != 0) {
228  struct sigaction act;
229  act.sa_sigaction = abort_timeout_handler;
230  act.sa_flags = SA_SIGINFO;
231  sigaction(SIGALRM, &act, NULL);
232  alarm(seconds);
233  }
234  }
235 }
236 
237 
238 static int
239 realmain(int argc, char* const* argv)
240 {
241  Args args;
242  args.parse(argc, argv); // may call exit()
243 
246 
247  // -------------------------------------------------------
248  // 0. MPI initialize
249  // -------------------------------------------------------
250  MPI_Init(&argc, (char***)&argv);
251 
252  int myRank, numRanks;
253  MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
254  MPI_Comm_size(MPI_COMM_WORLD, &numRanks);
255 
256  // -------------------------------------------------------
257  // 0. Debugging hook
258  // -------------------------------------------------------
259  const char* HPCPROF_WAIT = getenv("HPCPROF_WAIT");
260  if (HPCPROF_WAIT) {
261  int waitRank = 0;
262  if (strlen(HPCPROF_WAIT) > 0) {
263  waitRank = atoi(HPCPROF_WAIT);
264  }
265 
266  volatile int DEBUGGER_WAIT = 1;
267  if (myRank == waitRank) {
268  while (DEBUGGER_WAIT);
269  }
270  }
271 
272  // -------------------------------------------------------
273  // 0. Make empty Experiment database (ensure file system works)
274  // -------------------------------------------------------
275  if (myRank == 0)
276  args.makeDatabaseDir();
277 
278  char dbDirBuf[PATH_MAX];
279  if (myRank == 0) {
280  memset(dbDirBuf, '\0', PATH_MAX); // avoid artificial valgrind warnings
281  strncpy(dbDirBuf, args.db_dir.c_str(), PATH_MAX);
282  dbDirBuf[PATH_MAX - 1] = '\0';
283  }
284 
285  MPI_Bcast((void*)dbDirBuf, PATH_MAX, MPI_CHAR, 0, MPI_COMM_WORLD);
286  args.db_dir = dbDirBuf;
287 
288  // -------------------------------------------------------
289  // 1a. Create local CCT (from local set of profile files)
290  // -------------------------------------------------------
291  Prof::CallPath::Profile* profLcl = NULL;
292 
293  vector<uint> groupIdToGroupSizeMap; // only initialized for rank 0
294 
296  myNormalizeProfileArgs(args.profileFiles, groupIdToGroupSizeMap,
297  myRank, numRanks);
298 
299  if (nArgs.paths->size() == 0 && myRank == 0) {
300  std::cerr << "ERROR: command line directories"
301  " contain no .hpcrun files; no database generated\n";
302  prof_abort(-1);
303  }
304 
309  Analysis::Util::UIntVec* groupMap =
310  (nArgs.groupMax > 1) ? nArgs.groupMap : NULL;
311 
312  profLcl = Analysis::CallPath::read(*nArgs.paths, groupMap, mergeTy, rFlags);
313 
314  // -------------------------------------------------------
315  // 1b. Create canonical CCT (metrics merged by <group>.<name>.*)
316  // -------------------------------------------------------
317  Prof::CallPath::Profile* profGbl = NULL;
318 
319  // Post-INVARIANT: rank 0's 'profLcl' is the canonical CCT. Metrics
320  // are merged (and sorted by always merging left-child before right)
321  ParallelAnalysis::reduce(profLcl, myRank, numRanks);
322 
323  ParallelAnalysis::reduce(&profLcl->directorySet(), myRank, numRanks);
324 
325  if (myRank == 0) {
326  profGbl = profLcl;
327  profLcl = NULL;
328  }
329 
330  // Post-INVARIANT: 'profGbl' is the canonical CCT
331  ParallelAnalysis::broadcast(profGbl, myRank);
332 
333  if (myRank == 0) {
334  profGbl->metricMgr()->mergePerfEventStatistics_finalize(numRanks - 1);
335  }
336 
337  ParallelAnalysis::broadcast(profGbl->directorySet(), myRank);
338 
339  delete profLcl;
340 
341  // -------------------------------------------------------
342  // 1c. Add static structure to canonical CCT; form dense node ids
343  //
344  // Post-INVARIANT: each process has canonical CCT with dense node
345  // ids; corresponding nodes have idential ids.
346  // -------------------------------------------------------
347 
348  Prof::Struct::Tree* structure = new Prof::Struct::Tree("");
349  if (!args.structureFiles.empty()) {
350  Analysis::CallPath::readStructure(structure, args);
351  }
352  profGbl->structure(structure);
353 
354 
355  // N.B.: Ensures that each rank adds static structure in the same
356  // order so that new corresponding nodes have identical node ids.
357  bool printProgress = (myRank == 0);
359  args.doNormalizeTy,
360  printProgress);
361 
362  // N.B.: Dense ids are assigned w.r.t. Prof::CCT::...::cmpByStructureInfo()
363  DIAG_MsgIf(DBG_PROF_MPI, myRank << ". numcct before: " << profGbl->cct()->maxDenseId() << std::endl);
364 
365  profGbl->cct()->makeDensePreorderIds();
366 
367  DIAG_MsgIf(DBG_PROF_MPI, myRank << ". numcct after: " << profGbl->cct()->maxDenseId() << std::endl);
368 
369  // -------------------------------------------------------
370  // 2a. Create summary metrics for canonical CCT
371  //
372  // Post-INVARIANT: rank 0's 'profGbl' contains summary metrics
373  // -------------------------------------------------------
374  DIAG_MsgIf(DBG_PROF_MPI, myRank << ". stage 2a: makeSummaryMetrics" << std::endl);
375 
376  makeSummaryMetrics(*profGbl, args, nArgs, groupIdToGroupSizeMap,
377  myRank, numRanks);
378 
379  // -------------------------------------------------------
380  // 2b. Prune and normalize canonical CCT
381  // -------------------------------------------------------
382  DIAG_MsgIf(DBG_PROF_MPI, myRank << ". stage 2b: pruneBySummaryMetrics" << std::endl);
383 
384  uint prunedNodesSz = profGbl->cct()->maxDenseId() + 1;
385  uint8_t* prunedNodes = new uint8_t[prunedNodesSz];
386  memset(prunedNodes, 0, prunedNodesSz * sizeof(uint8_t));
387 
388  if (myRank == 0) {
389  // Disable pruning when making a metric database because it causes
390  // makeThreadMetrics_Lcl(), which uses CCT::MrgFlg_CCTMergeOnly,
391  // to under-compute values for thread-level metrics.
392  if (!args.db_makeMetricDB) {
393  Analysis::CallPath::pruneBySummaryMetrics(*profGbl, prunedNodes);
394  }
395  }
396 
397  DIAG_MsgIf(DBG_PROF_MPI, myRank << ". stage 2b1: broadcast prunedNodes" << std::endl);
398 
399  MPI_Bcast(prunedNodes, prunedNodesSz, MPI_BYTE, 0, MPI_COMM_WORLD);
400 
401  if (myRank != 0) {
402  profGbl->cct()->pruneCCTByNodeId(prunedNodes);
403  }
404  delete[] prunedNodes;
405 
406  DIAG_MsgIf(DBG_PROF_MPI, myRank << ". stage 2b2: normalize" << std::endl);
407 
408  Analysis::CallPath::normalize(*profGbl, args.agent, args.doNormalizeTy);
409 
410  if (myRank == 0) {
411  // Apply after all CCT pruning/normalization is completed.
413  }
414 
415  // N.B.: Dense ids are assigned w.r.t. Prof::CCT::...::cmpByStructureInfo()
416  profGbl->cct()->makeDensePreorderIds();
417 
418  // -------------------------------------------------------
419  // 2c. Create thread-level metric DB // Normalize trace files
420  // -------------------------------------------------------
421  DIAG_MsgIf(DBG_PROF_MPI, myRank << ". stage 2c: makeThreadMetrics" << std::endl);
422 
423  makeThreadMetrics(*profGbl, args, nArgs, groupIdToGroupSizeMap,
424  myRank, numRanks);
425 
426  // ------------------------------------------------------------
427  // 3. Generate Experiment database
428  // INVARIANT: database dir already exists
429  // ------------------------------------------------------------
430  DIAG_MsgIf(DBG_PROF_MPI, myRank << ". stage 3: pruneStructTree" << std::endl);
431 
433 
434  if (myRank == 0) {
435  if (args.title.empty()) {
436  args.title = profGbl->name();
437  }
438 
439  if (!args.db_makeMetricDB) {
440  profGbl->metricMgr()->zeroDBInfo();
441  }
442 
443  Analysis::CallPath::makeDatabase(*profGbl, args);
444  }
445  else {
447  }
448 
449  // -------------------------------------------------------
450  // Cleanup/MPI finalize
451  // -------------------------------------------------------
452  nArgs.destroy();
453 
454  delete profGbl;
455 
456  MPI_Finalize();
457 
458  return 0;
459 }
460 
461 
462 //****************************************************************************
463 
464 // myNormalizeProfileArgs: creates canonical list of profiles files and
465 // distributes chunks of size ceil(numFiles / numRanks) to each process.
466 // The last process may have a smaller chunk than the others.
469  vector<uint>& groupIdToGroupSizeMap,
470  int myRank, int numRanks)
471 {
473 
474  char* sendFilesBuf = NULL;
475  uint sendFilesBufSz = 0;
476  uint sendFilesChunkSz = 0;
477  const uint groupIdLen = 1; // see asssertion below
478  uint pathLenMax = 0;
479  uint groupIdMax = 0;
480 
481  // -------------------------------------------------------
482  // root creates canonical and grouped list of files
483  // -------------------------------------------------------
484 
485  if (myRank == 0) {
488 
489  Analysis::Util::StringVec* canonicalFiles = nArgs.paths;
490  pathLenMax = nArgs.pathLenMax;
491  groupIdMax = nArgs.groupMax;
492 
493  DIAG_Assert(nArgs.groupMax <= UCHAR_MAX, "myNormalizeProfileArgs: 'groupMax' cannot be packed into a uchar!");
494 
495  uint chunkSz = (uint)
496  ceil( (double)canonicalFiles->size() / (double)numRanks);
497 
498  sendFilesChunkSz = chunkSz * (groupIdLen + pathLenMax + 1);
499  sendFilesBufSz = sendFilesChunkSz * numRanks;
500  sendFilesBuf = new char[sendFilesBufSz];
501  memset(sendFilesBuf, '\0', sendFilesBufSz);
502 
503  groupIdToGroupSizeMap.resize(groupIdMax + 1);
504 
505  for (uint i = 0, j = 0; i < canonicalFiles->size();
506  i++, j += (groupIdLen + pathLenMax + 1)) {
507  const std::string& nm = (*canonicalFiles)[i];
508  uint groupId = (*nArgs.groupMap)[i];
509 
510  groupIdToGroupSizeMap[groupId]++;
511 
512  // pack into sendFilesBuf
513  sendFilesBuf[j] = (char)groupId;
514  strncpy(&(sendFilesBuf[j + groupIdLen]), nm.c_str(), pathLenMax);
515  sendFilesBuf[j + groupIdLen + pathLenMax] = '\0';
516  }
517 
518  nArgs.destroy();
519  }
520 
521  // -------------------------------------------------------
522  // prepare parameters for scatter
523  // -------------------------------------------------------
524 
525  const uint metadataBufSz = 3;
526  uint metadataBuf[metadataBufSz];
527  metadataBuf[0] = sendFilesChunkSz;
528  metadataBuf[1] = pathLenMax;
529  metadataBuf[2] = groupIdMax;
530 
531  MPI_Bcast((void*)metadataBuf, metadataBufSz, MPI_UNSIGNED,
532  0, MPI_COMM_WORLD);
533 
534  if (myRank != 0) {
535  sendFilesChunkSz = metadataBuf[0];
536  pathLenMax = metadataBuf[1];
537  groupIdMax = metadataBuf[2];
538  }
539 
540  // -------------------------------------------------------
541  // evenly distribute profile files across all processes
542  // -------------------------------------------------------
543 
544  uint recvFilesChunkSz = sendFilesChunkSz;
545  const char* recvFilesBuf = new char[recvFilesChunkSz];
546 
547  MPI_Scatter((void*)sendFilesBuf, sendFilesChunkSz, MPI_CHAR,
548  (void*)recvFilesBuf, recvFilesChunkSz, MPI_CHAR,
549  0, MPI_COMM_WORLD);
550 
551  delete[] sendFilesBuf;
552 
553 
554  for (uint i = 0; i < recvFilesChunkSz; i += (groupIdLen + pathLenMax + 1)) {
555  uint groupId = recvFilesBuf[i];
556  const char* nm_cstr = &recvFilesBuf[i + groupIdLen];
557  string nm = nm_cstr;
558  if (!nm.empty()) {
559  out.paths->push_back(nm);
560  out.groupMap->push_back(groupId);
561  }
562  }
563 
564  out.pathLenMax = pathLenMax;
565  out.groupMax = groupIdMax;
566 
567  delete[] recvFilesBuf;
568 
569  if (0) {
570  for (uint i = 0; i < out.paths->size(); ++i) {
571  const std::string& nm = (*out.paths)[i];
572  std::cout << "[" << myRank << "]: " << nm << std::endl;
573  }
574  }
575 
576  return out;
577 }
578 
579 
580 //***************************************************************************
581 
582 // makeSummaryMetrics: Assumes 'profGbl' is the canonical CCT (with
583 // structure and with canonical ids).
584 static void
586  const Analysis::Args& args,
588  const vector<uint>& groupIdToGroupSizeMap,
589  int myRank, int numRanks)
590 {
591  uint mDrvdBeg = 0, mDrvdEnd = 0; // [ )
592  uint mXDrvdBeg = 0, mXDrvdEnd = 0; // [ )
593 
594  vector<VMAIntervalSet*> groupIdToGroupMetricsMap(nArgs.groupMax + 1, NULL);
595 
596  makeDerivedMetricDescs(profGbl, args,
597  mDrvdBeg, mDrvdEnd, mXDrvdBeg, mXDrvdEnd,
598  groupIdToGroupMetricsMap, groupIdToGroupSizeMap,
599  myRank);
600 
601  Prof::Metric::Mgr& mMgrGbl = *profGbl.metricMgr();
602  Prof::CCT::ANode* cctRoot = profGbl.cct()->root();
603 
604  // -------------------------------------------------------
605  // compute local contribution summary metrics (accumulate function)
606  // -------------------------------------------------------
607  cctRoot->computeMetricsIncr(mMgrGbl, mDrvdBeg, mDrvdEnd,
609 
610  for (uint i = 0; i < nArgs.paths->size(); ++i) {
611  const string& fnm = (*nArgs.paths)[i];
612  uint groupId = (*nArgs.groupMap)[i];
613  makeSummaryMetrics_Lcl(profGbl, fnm, args, groupId, nArgs.groupMax,
614  groupIdToGroupMetricsMap, myRank);
615  }
616 
617  // -------------------------------------------------------
618  // create summary metrics via reduction (combine function)
619  // -------------------------------------------------------
620 
621  // 1. Change definitions of derived metrics [mDrvdBeg, mDrvdEnd)
622  // since the 'combine' function will be used during the metric
623  // reduction. Metric inputs point to accumulators [mXDrvdBeg,
624  // mXDrvdEnd) rather input values.
625  for (uint i = mDrvdBeg, j = mXDrvdBeg; i < mDrvdEnd; ++i) {
626  Prof::Metric::ADesc* m = mMgrGbl.metric(i);
628  dynamic_cast<Prof::Metric::DerivedIncrDesc*>(m);
629  DIAG_Assert(mm, DIAG_UnexpectedInput);
630 
631  Prof::Metric::AExprIncr* expr = mm->expr();
632  if (expr) {
633  for (uint k = 0; k < expr->numAccum(); ++k)
634  expr->srcId(k, j++);
635  }
636  }
637 
638  // 2. Initialize temporary accumulators [mXDrvdBeg, mXDrvdEnd) used
639  // during the summary metrics reduction
640  cctRoot->computeMetricsIncr(mMgrGbl, mXDrvdBeg, mXDrvdEnd,
642 
643  // 3. Reduction
644  uint maxCCTId = profGbl.cct()->maxDenseId();
645 
646  ParallelAnalysis::PackedMetrics* packedMetrics =
647  new ParallelAnalysis::PackedMetrics(maxCCTId + 1, mXDrvdBeg, mXDrvdEnd,
648  mDrvdBeg, mDrvdEnd);
649 
650  // Post-INVARIANT: rank 0's 'profGbl' contains summary metrics
651  ParallelAnalysis::reduce(std::make_pair(&profGbl, packedMetrics),
652  myRank, numRanks);
653 
654  // -------------------------------------------------------
655  // finalize metrics
656  // -------------------------------------------------------
657 
658  if (myRank == 0) {
659 
660  for (uint i = 0; i < mMgrGbl.size(); ++i) {
661  Prof::Metric::ADesc* m = mMgrGbl.metric(i);
663  }
664  }
665 
666  for (uint grpId = 1; grpId < groupIdToGroupMetricsMap.size(); ++grpId) {
667  delete groupIdToGroupMetricsMap[grpId];
668  }
669 
670  delete packedMetrics;
671 }
672 
673 
674 static void
676  const Analysis::Args& args,
678  const vector<uint>& groupIdToGroupSizeMap,
679  int myRank, int numRanks)
680 {
681  for (uint i = 0; i < nArgs.paths->size(); ++i) {
682  string& fnm = (*nArgs.paths)[i];
683  uint groupId = (*nArgs.groupMap)[i];
684  makeThreadMetrics_Lcl(profGbl, fnm, args, groupId, nArgs.groupMax, myRank);
685  }
686 }
687 
688 
689 static uint
691  const Analysis::Args& args,
692  uint& mDrvdBeg, uint& mDrvdEnd,
693  uint& mXDrvdBeg, uint& mXDrvdEnd,
694  vector<VMAIntervalSet*>& groupIdToGroupMetricsMap,
695  const vector<uint>& groupIdToGroupSizeMap,
696  int myRank)
697 {
698  Prof::Metric::Mgr& mMgrGbl = *(profGbl.metricMgr());
699 
700  uint numSrc = mMgrGbl.size();
701  uint mSrcBeg = 0, mSrcEnd = numSrc; // [ )
702 
703  uint numDrvd = 0;
704  mDrvdBeg = mDrvdEnd = 0; // [ )
705  mXDrvdBeg = mXDrvdEnd = 0; // [ )
706 
707  // -------------------------------------------------------
708  // official set of derived metrics
709  // -------------------------------------------------------
710 
711  bool needAllStats =
714 
715  mDrvdBeg = mMgrGbl.makeSummaryMetricsIncr(needAllStats, mSrcBeg, mSrcEnd);
716  if (mDrvdBeg != Prof::Metric::Mgr::npos) {
717  mDrvdEnd = mMgrGbl.size();
718  numDrvd = (mDrvdEnd - mDrvdBeg);
719  }
720 
721  for (uint i = mSrcBeg; i < mSrcEnd; ++i) {
722  Prof::Metric::ADesc* m = mMgrGbl.metric(i);
723  m->isVisible(false);
724  }
725 
726  for (uint i = mDrvdBeg; i < mDrvdEnd; ++i) {
727  Prof::Metric::ADesc* m = mMgrGbl.metric(i);
728 
729  uint groupId = 1; // default group-id
730 
731  // find groupId embedded in metric descriptor name
732  const string& nmPfx = m->namePfx();
733  if (!nmPfx.empty()) {
734  groupId = (uint)StrUtil::toUInt64(nmPfx);
735  }
736  DIAG_Assert(groupId > 0, DIAG_UnexpectedInput);
737  DIAG_Assert(groupId < groupIdToGroupMetricsMap.size(), DIAG_UnexpectedInput);
738 
739  // rank 0: set the number of inputs
740  if (myRank == 0) {
742  dynamic_cast<Prof::Metric::DerivedIncrDesc*>(m);
743  DIAG_Assert(mm, DIAG_UnexpectedInput);
744 
745  // N.B.: groupIdToGroupSizeMap is only initialized for rank 0
746  uint numInputs = groupIdToGroupSizeMap[groupId]; // / <n> TODO:threads
747  if (mm->expr()) {
748  mm->expr()->numSrcFxd(numInputs);
749  }
750  }
751 
752  // populate groupIdToGroupMetricsMap map
753  VMAIntervalSet*& ivalset = groupIdToGroupMetricsMap[groupId];
754  if (!ivalset) {
755  ivalset = new VMAIntervalSet;
756  }
757  ivalset->insert(i, i + 1); // [ )
758  }
759 
760  // -------------------------------------------------------
761  // make temporary set of extra derived metrics (for reduction)
762  // -------------------------------------------------------
763  mXDrvdBeg = mMgrGbl.makeSummaryMetricsIncr(needAllStats, mSrcBeg, mSrcEnd);
764  if (mXDrvdBeg != Prof::Metric::Mgr::npos) {
765  mXDrvdEnd = mMgrGbl.size();
766  }
767 
768  for (uint i = mXDrvdBeg; i < mXDrvdEnd; ++i) {
769  Prof::Metric::ADesc* m = mMgrGbl.metric(i);
770  m->isVisible(false);
771  }
772 
773  profGbl.isMetricMgrVirtual(false);
774 
775  return numDrvd;
776 }
777 
778 
779 // makeSummaryMetrics_Lcl: Make summary metrics.
780 //
781 // Assumes:
782 // - 'profGbl' is the canonical CCT (with structure and with
783 // canonical ids)
784 // - each thread-level CCT is always a subset of 'profGbl' (the
785 // canonical CCT); in other words, 'profGbl' should not be pruned
786 // in any way!
787 // - 'args' contains the correct final experiment database.
788 //
789 // FIXME: abstract between makeSummaryMetrics_Lcl() & makeThreadMetrics_Lcl()
790 static void
792  const string& profileFile,
793  const Analysis::Args& args, uint groupId, uint groupMax,
794  vector<VMAIntervalSet*>& groupIdToGroupMetricsMap,
795  int myRank)
796 {
797  Prof::Metric::Mgr* mMgrGbl = profGbl.metricMgr();
798  Prof::CCT::Tree* cctGbl = profGbl.cct();
799  Prof::CCT::ANode* cctRootGbl = cctGbl->root();
800 
801  // -------------------------------------------------------
802  // read profile file
803  // -------------------------------------------------------
806  uint rGroupId = (groupMax > 1) ? groupId : 0;
807 
809  Analysis::CallPath::read(profileFile, rGroupId, rFlags);
810 
811  // -------------------------------------------------------
812  // merge into canonical CCT
813  // -------------------------------------------------------
815  int mergeFlg = (Prof::CCT::MrgFlg_AssertCCTMergeOnly);
816 
817  // Add *some* structure information to the leaves of 'prof' so that
818  // it will be merged successfully with the structured canonical CCT
819  // 'profGbl'.
820  //
821  // Background: When CCT::Stmts are merged in
822  // Analysis::CallPath::coalesceStmts(CallPath::Profile), IP/LIP
823  // information is not retained. This means that when merging 'prof'
824  // into 'profGbl' (using CallPath::Profile::merge()), many leaves in
825  // 'prof' will not find their corresponding node in 'profGbl' unless
826  // corrective measures are taken.
827  prof->structure(profGbl.structure());
829  prof->structure(NULL);
830 
831  uint mBeg = profGbl.merge(*prof, mergeTy, mergeFlg); // [closed begin
832  uint mEnd = mBeg + prof->metricMgr()->size(); // open end)
833 
834  // -------------------------------------------------------
835  // compute local incl/excl sampled metrics and update local derived metrics
836  // -------------------------------------------------------
837 
838  // 1. Batch compute local sampled metrics
839  VMAIntervalSet ivalsetIncl;
840  VMAIntervalSet ivalsetExcl;
841 
842  for (uint mId = mBeg; mId < mEnd; ++mId) {
843  Prof::Metric::ADesc* m = mMgrGbl->metric(mId);
844  if (m->type() == Prof::Metric::ADesc::TyIncl) {
845  ivalsetIncl.insert(VMAInterval(mId, mId + 1)); // [ )
846  }
847  else if (m->type() == Prof::Metric::ADesc::TyExcl) {
848  ivalsetExcl.insert(VMAInterval(mId, mId + 1)); // [ )
849  }
850  }
851 
852  cctRootGbl->aggregateMetricsIncl(ivalsetIncl);
853  cctRootGbl->aggregateMetricsExcl(ivalsetExcl);
854 
855 
856  // 2. Batch compute local derived metrics
857  const VMAIntervalSet* ivalsetDrvd = groupIdToGroupMetricsMap[groupId];
858  if (ivalsetDrvd) {
859  DIAG_Assert(ivalsetDrvd->size() == 1, DIAG_UnexpectedInput);
860  const VMAInterval& ival = *(ivalsetDrvd->begin());
861  uint mDrvdBeg = (uint)ival.beg();
862  uint mDrvdEnd = (uint)ival.end();
863 
864  DIAG_MsgIf(0, "[" << myRank << "] grp " << groupId << ": [" << mDrvdBeg << ", " << mDrvdEnd << ")");
865  cctRootGbl->computeMetricsIncr(*mMgrGbl, mDrvdBeg, mDrvdEnd,
867  }
868 
869  // -------------------------------------------------------
870  // reinitialize metric values for next time
871  // -------------------------------------------------------
872 
873  // TODO: This really should (a) come immediately after the MetricMgr
874  // merge above and (b) use FnInitSrc (not 0). However, to do this
875  // we would need to (a) split the MetricMgr merge and CCT merge into
876  // two; and (b) use a CCT init (which whould initialize using
877  // assignment) instead of CCT::merge() (which initializes based on
878  // addition against 0).
879  cctRootGbl->zeroMetricsDeep(mBeg, mEnd); // cf. FnInitSrc
880 
881  delete prof;
882 }
883 
884 
885 // makeThreadMetrics_Lcl: Make thread-level metric database.
886 //
887 // Makes same assumptions as makeSummaryMetrics_Lcl but with one key
888 // exception: Each thread-level CCT does not have to be a subset of
889 // 'profGbl' (the canonical CCT); in other words, 'profGbl' may be
890 // pruned.
891 static void
893  const string& profileFile,
894  const Analysis::Args& args, uint groupId, uint groupMax,
895  int myRank)
896 {
897  Prof::Metric::Mgr* mMgrGbl = profGbl.metricMgr();
898  Prof::CCT::Tree* cctGbl = profGbl.cct();
899  Prof::CCT::ANode* cctRootGbl = cctGbl->root();
900 
901  // -------------------------------------------------------
902  // read profile file
903  // -------------------------------------------------------
906  uint rGroupId = (groupMax > 1) ? groupId : 0;
907 
909  Analysis::CallPath::read(profileFile, rGroupId, rFlags);
910 
911  // -------------------------------------------------------
912  // merge into canonical CCT
913  // -------------------------------------------------------
917 
918  // Add *some* structure information to the leaves of 'prof' so that
919  // it will be merged successfully with the structured canonical CCT
920  // 'profGbl'.
921  //
922  // Background: When CCT::Stmts are merged in
923  // Analysis::CallPath::coalesceStmts(CallPath::Profile), IP/LIP
924  // information is not retained. This means that when merging 'prof'
925  // into 'profGbl' (using CallPath::Profile::merge()), many leaves in
926  // 'prof' will not find their corresponding node in 'profGbl' unless
927  // corrective measures are taken.
928  prof->structure(profGbl.structure());
930  prof->structure(NULL);
931 
932  uint mBeg = profGbl.merge(*prof, mergeTy, mergeFlg); // [closed begin
933 
934  if (args.db_makeMetricDB) {
935  uint mEnd = mBeg + prof->metricMgr()->size(); // open end)
936 
937  // -------------------------------------------------------
938  // compute local incl/excl sampled metrics
939  // -------------------------------------------------------
940 
941  VMAIntervalSet ivalsetIncl;
942  VMAIntervalSet ivalsetExcl;
943 
944  for (uint mId = mBeg; mId < mEnd; ++mId) {
945  Prof::Metric::ADesc* m = mMgrGbl->metric(mId);
946  if (m->type() == Prof::Metric::ADesc::TyIncl) {
947  ivalsetIncl.insert(VMAInterval(mId, mId + 1)); // [ )
948  }
949  else if (m->type() == Prof::Metric::ADesc::TyExcl) {
950  ivalsetExcl.insert(VMAInterval(mId, mId + 1)); // [ )
951  }
952  }
953 
954  cctRootGbl->aggregateMetricsIncl(ivalsetIncl);
955  cctRootGbl->aggregateMetricsExcl(ivalsetExcl);
956 
957  // -------------------------------------------------------
958  // write local sampled metric values into database
959  // -------------------------------------------------------
960 
961  string dbFnm = makeDBFileName(args.db_dir, groupId, profileFile);
962  writeMetricsDB(profGbl, mBeg, mEnd, dbFnm);
963 
964  // -------------------------------------------------------
965  // reinitialize metric values for next time
966  // -------------------------------------------------------
967 
968  // TODO: see corresponding comments in makeSummaryMetrics_Lcl()
969  cctRootGbl->zeroMetricsDeep(mBeg, mEnd); // cf. FnInitSrc
970  }
971 
972  delete prof;
973 }
974 
975 
976 static string
977 makeDBFileName(const string& dbDir, uint groupId, const string& profileFile)
978 {
979  string grpStr = StrUtil::toStr(groupId);
980 
981  string fnm_base = FileUtil::rmSuffix(FileUtil::basename(profileFile.c_str()));
982 
983  string fnm = grpStr + "." + fnm_base + "." + HPCPROF_MetricDBSfx;
984 
985  string metricDBFnm = dbDir + "/" + fnm;
986  return metricDBFnm;
987 }
988 
989 
990 // [mBegId, mEndId)
991 static void
993  const string& metricDBFnm)
994 {
995  const Prof::CCT::Tree& cct = *(profGbl.cct());
996 
997  // -------------------------------------------------------
998  // pack metrics into dense matrix
999  // -------------------------------------------------------
1000  uint maxCCTId = cct.maxDenseId();
1001 
1002  ParallelAnalysis::PackedMetrics packedMetrics(maxCCTId + 1, mBegId, mEndId,
1003  mBegId, mEndId);
1004 
1005  ParallelAnalysis::packMetrics(profGbl, packedMetrics);
1006 
1007  // -------------------------------------------------------
1008  // write data
1009  // -------------------------------------------------------
1010 
1011  FILE* fs = hpcio_fopen_w(metricDBFnm.c_str(), 1);
1012  if (!fs) {
1013  std::string errorString;
1014  hpcrun_getFileErrorString(metricDBFnm, errorString);
1015 
1016  DIAG_EMsg("failed opening profile result file for writing " <<
1017  errorString << "; aborting.");
1018 
1019  prof_abort(-1);
1020  }
1021  DIAG_MsgIf(0, "writeMetricsDB: " << metricDBFnm);
1022 
1023  uint numNodes = packedMetrics.numNodes() - 1;
1024 
1025  // 1. header
1027  hdr.numNodes = numNodes;
1028  hdr.numMetrics = mEndId - mBegId; // [mBegId mEndId)
1029 
1030  int ret;
1031  ret = hpcmetricDB_fmt_hdr_fwrite(&hdr, fs);
1032  if (ret == HPCFMT_ERR) goto badwrite;
1033 
1034  // 2. metric values
1035  // - first row corresponds to node 1.
1036  // - first column corresponds to first sampled metric.
1037  // cf. ParallelAnalysis::unpackMetrics:
1038 
1039  for (uint nodeId = 1; nodeId < numNodes + 1; ++nodeId) {
1040  for (uint mId1 = 0, mId2 = mBegId; mId2 < mEndId; ++mId1, ++mId2) {
1041  double mval = packedMetrics.idx(nodeId, mId1);
1042  DIAG_MsgIf(0, " " << nodeId << " -> " << mval);
1043  ret = hpcfmt_real8_fwrite(mval, fs);
1044  if (ret == HPCFMT_ERR) goto badwrite;
1045  }
1046  }
1047 
1048  hpcio_fclose(fs);
1049  return;
1050 
1051 badwrite:
1052  {
1053  std::string errorString;
1054  hpcrun_getFileErrorString(metricDBFnm, errorString);
1055 
1056  DIAG_EMsg("failed writing profile result file" <<
1057  errorString << "; aborting.");
1058  prof_abort(-1);
1059  }
1060 }
1061 
1062 
1063 //***************************************************************************
1064 
1065 static void
1066 writeStructure(const Prof::Struct::Tree& structure, const char* baseNm,
1067  int myRank)
1068 {
1069  string fnm = makeFileName(baseNm, "xml", myRank);
1070  std::ostream* os = IOUtil::OpenOStream(fnm.c_str());
1071  Prof::Struct::writeXML(*os, structure, true);
1072  IOUtil::CloseStream(os);
1073 }
1074 
1075 
1076 static void
1077 writeProfile(const Prof::CallPath::Profile& prof, const char* baseNm,
1078  int myRank)
1079 {
1080  // Only safe if static structure has not been added
1081  //string fnm_hpcrun = makeFileName(baseNm, "txt", myRank);
1082  //FILE* fs = hpcio_fopen_w(fnm_hpcrun.c_str(), 1);
1083  //Prof::CallPath::Profile::fmt_fwrite(prof, fs, 0);
1084  //hpcio_fclose(fs);
1085 
1086  string fnm_xml = makeFileName(baseNm, "xml", myRank);
1087  std::ostream* os = IOUtil::OpenOStream(fnm_xml.c_str());
1088  prof.cct()->writeXML(*os, 0, 0, Prof::CCT::Tree::OFlg_Debug);
1089  IOUtil::CloseStream(os);
1090 }
1091 
1092 
1093 static std::string
1094 makeFileName(const char* baseNm, const char* ext, int myRank)
1095 {
1096  return string(baseNm) + "-" + StrUtil::toStr(myRank) + "." + ext;
1097 }
1098 
1099 //****************************************************************************
1100 
Definition: Args.hpp:79
void makeDatabaseDir()
Definition: Args.cpp:203
void prof_abort(int error_code)
Definition: main.cpp:98
void aggregateMetricsIncl(uint mBegId, uint mEndId)
Definition: CCT-Tree.cpp:458
void CloseStream(std::istream *s)
Definition: IOUtil.cpp:127
void readStructure(Prof::Struct::Tree *structure, const Analysis::Args &args)
Definition: CallPath.cpp:210
void srcId(int i, uint x)
std::string db_dir
Definition: Args.hpp:199
void applySummaryMetricAgents(Prof::CallPath::Profile &prof, string agent)
Definition: CallPath.cpp:1015
NormalizeProfileArgs_t normalizeProfileArgs(const StringVec &inPaths)
Definition: Util.cpp:179
void normalize(Prof::CallPath::Profile &prof, string agent, bool doNormalizeTy)
bool isVisible() const
uint prof_metrics
Definition: Args.hpp:176
uint64_t toUInt64(const char *str, unsigned *endidx)
Definition: StrUtil.cpp:189
#define DIAG_EMsg(...)
Definition: diagnostics.h:251
string toStr(const int x, int base)
Definition: StrUtil.cpp:243
static void makeSummaryMetrics(Prof::CallPath::Profile &profGbl, const Analysis::Args &args, const Analysis::Util::NormalizeProfileArgs_t &nArgs, const vector< uint > &groupIdToGroupSizeMap, int myRank, int numRanks)
Definition: main.cpp:585
static void makeSummaryMetrics_Lcl(Prof::CallPath::Profile &profGbl, const string &profileFile, const Analysis::Args &args, uint groupId, uint groupMax, vector< VMAIntervalSet *> &groupIdToGroupMetricsMap, int myRank)
Definition: main.cpp:791
std::vector< std::string > structureFiles
Definition: Args.hpp:128
void writeXML(std::ostream &os, const Prof::Struct::Tree &strctTree, bool prettyPrint)
static uint makeDerivedMetricDescs(Prof::CallPath::Profile &profGbl, const Analysis::Args &args, uint &mDrvdBeg, uint &mDrvdEnd, uint &mXDrvdBeg, uint &mXDrvdEnd, vector< VMAIntervalSet *> &groupIdToGroupMetricsMap, const vector< uint > &groupIdToGroupSizeMap, int myRank)
Definition: main.cpp:690
static void writeProfile(const Prof::CallPath::Profile &prof, const char *baseNm, int myRank) __attribute__((unused))
Definition: main.cpp:1077
ANode * root() const
Definition: CCT-Tree.hpp:160
static void abort_timeout_handler(int sig, siginfo_t *siginfo, void *context)
Definition: main.cpp:216
void overlayStaticStructureMain(Prof::CallPath::Profile &prof, string agent, bool doNormalizeTy, bool printProgress)
Definition: CallPath.cpp:347
void reduce(T object, int myRank, int numRanks, MPI_Comm comm=MPI_COMM_WORLD)
void pruneStructTree(Prof::CallPath::Profile &prof)
Definition: CallPath.cpp:839
void zeroDBInfo() const
Definition: Metric-Mgr.cpp:721
static void makeThreadMetrics(Prof::CallPath::Profile &profGbl, const Analysis::Args &args, const Analysis::Util::NormalizeProfileArgs_t &nArgs, const vector< uint > &groupIdToGroupSizeMap, int myRank, int numRanks)
Definition: main.cpp:675
abort
Definition: names.cpp:1
const StringSet & traceFileNameSet() const
VMA beg() const
std::vector< uint > UIntVec
Definition: Util.hpp:109
static RealPathMgr & singleton()
std::string searchPathStr
Definition: Args.hpp:119
uint makeSummaryMetricsIncr(bool needAllStats, uint srcBegId=Mgr::npos, uint srcEndId=Mgr::npos)
Definition: Metric-Mgr.cpp:235
void mergePerfEventStatistics_finalize(int num_profiles)
Definition: Metric-Mgr.cpp:222
void makeDatabase(Prof::CallPath::Profile &prof, const Analysis::Args &args)
Definition: CallPath.cpp:1106
int MPI_Init(int *argc, char ***argv)
Definition: MPI_Init.c:88
static Analysis::Util::NormalizeProfileArgs_t myNormalizeProfileArgs(const Analysis::Util::StringVec &profileFiles, vector< uint > &groupIdToGroupSizeMap, int myRank, int numRanks)
Definition: main.cpp:468
void parse(int argc, const char *const argv[])
Definition: Args.cpp:208
static bool MetricFlg_isSet(uint flags, MetricFlg x)
Definition: Args.hpp:154
std::ostream * OpenOStream(const char *filenm)
Definition: IOUtil.cpp:106
#define DIAG_MsgIf(ifexpr,...)
Definition: diagnostics.h:236
uint size() const
Definition: Metric-Mgr.hpp:153
virtual std::string message() const
Definition: Exception.hpp:134
exit
Definition: names.cpp:1
static void writeStructure(const Prof::Struct::Tree &structure, const char *baseNm, int myRank) __attribute__((unused))
Definition: main.cpp:1066
unsigned int uint
Definition: uint.h:124
void copyTraceFiles(const std::string &dstDir, const std::set< string > &srcFiles)
Definition: Util.cpp:586
void zeroMetricsDeep(uint mBegId, uint mEndId)
Definition: CCT-Tree.cpp:444
ComputedTy computedType() const
static const uint npos
Definition: Metric-Mgr.hpp:202
static std::string makeFileName(const char *baseNm, const char *ext, int myRank)
Definition: main.cpp:1094
static void writeMetricsDB(Prof::CallPath::Profile &profGbl, uint mBegId, uint mEndId, const string &metricDBFnm)
Definition: main.cpp:992
bool db_makeMetricDB
Definition: Args.hpp:204
void computeMetricsIncr(const Metric::Mgr &mMgr, uint mBegId, uint mEndId, Metric::AExprIncr::FnTy fn)
Definition: CCT-Tree.cpp:644
void __attribute__((weak))
Definition: hpctoolkit.c:64
int main(int argc, char *argv[])
Definition: main.cpp:125
uint merge(Profile &y, int mergeTy, uint mrgFlag=0)
uint maxDenseId() const
Definition: CCT-Tree.hpp:193
void broadcast(Prof::CallPath::Profile *&profile, int myRank, MPI_Comm comm)
std::pair< iterator, bool > insert(const VMA beg, const VMA end)
static void hpcprof_set_abort_timeout()
Definition: main.cpp:222
std::vector< std::string > profileFiles
Definition: Args.hpp:138
ADescTy type() const
#define DBG_PROF_MPI
Definition: main.cpp:105
volatile int DEBUGGER_WAIT
Definition: monitor.c:424
static int realmain(int argc, char *const *argv)
Definition: main.cpp:239
const std::string & searchPaths() const
const Metric::Mgr * metricMgr() const
const char * DIAG_UnexpectedInput
Prof::Struct::Tree * structure() const
void aggregateMetricsExcl(uint mBegId, uint mEndId)
Definition: CCT-Tree.cpp:505
std::string agent
Definition: Args.hpp:114
void pruneBySummaryMetrics(Prof::CallPath::Profile &prof, uint8_t *prunedNodes)
Definition: CallPath.cpp:805
uint makeDensePreorderIds()
Definition: CCT-Tree.cpp:232
static string makeDBFileName(const string &dbDir, uint groupId, const string &profileFile)
Definition: main.cpp:977
void noteStaticStructureOnLeaves(Prof::CallPath::Profile &prof)
Definition: CallPath.cpp:454
static const char HPCPROF_MetricDBSfx[]
Definition: hpcrun-fmt.h:102
#define NULL
Definition: ElfHelper.cpp:85
const std::string & namePfx() const
std::string title
Definition: Args.hpp:121
Prof::CallPath::Profile * read(const Util::StringVec &profileFiles, const Util::UIntVec *groupMap, int mergeTy, uint rFlags, uint mrgFlags)
Definition: CallPath.cpp:142
void pruneCCTByNodeId(const uint8_t *prunedNodes)
Definition: CCT-Tree.cpp:221
double idx(uint idxNodes, uint idxMetrics) const
Metric::ADesc * metric(uint i)
Definition: Metric-Mgr.hpp:131
std::ostream & writeXML(std::ostream &os, const Metric::Mgr *metricMgr, uint metricBeg=Metric::IData::npos, uint metricEnd=Metric::IData::npos, uint oFlags=0) const
Definition: CCT-Tree.cpp:281
void packMetrics(const Prof::CallPath::Profile &profile, ParallelAnalysis::PackedMetrics &packedMetrics)
virtual uint numSrcFxd() const
string basename(const char *fName)
Definition: FileUtil.cpp:90
static void makeThreadMetrics_Lcl(Prof::CallPath::Profile &profGbl, const string &profileFile, const Analysis::Args &args, uint groupId, uint groupMax, int myRank)
Definition: main.cpp:892
int hpcio_fclose(FILE *fs)
Definition: hpcio.c:152
static int hpcfmt_real8_fwrite(double val, FILE *outfs)
Definition: hpcfmt.h:247
const std::string & name() const
int hpcmetricDB_fmt_hdr_fwrite(hpcmetricDB_fmt_hdr_t *hdr, FILE *outfs)
Definition: hpcrun-fmt.c:1036
bool doNormalizeTy
Definition: Args.hpp:140
std::vector< std::string > StringVec
Definition: Util.hpp:108
void hpcrun_getFileErrorString(const std::string &fnm, std::string &errorString)
Definition: FileError.cpp:87
FILE * hpcio_fopen_w(const char *fnm, int overwrite)
Definition: hpcio.c:100
Metric::AExprIncr * expr() const
virtual uint numAccum() const
CCT::Tree * cct() const
string rmSuffix(const char *fName)
Definition: FileUtil.cpp:121