Skip to content

Commit 41fd1ea

Browse files
fweigdavidrohr
authored andcommitted
GPU/Standalone: Compute checksum of dumped data
Add an option to compute the checksum of dumped data on the fly when using --debug 6. Only prints the checksum instead of writing dumped data to file when this option is used.
1 parent c584edc commit 41fd1ea

4 files changed

Lines changed: 137 additions & 4 deletions

File tree

‎GPU/GPUTracking/Definitions/GPUSettingsList.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ AddOption(debugLevel, int32_t, -1, "debug", 'd', "Set debug level (-2 = silent,
339339
AddOption(allocDebugLevel, int32_t, 0, "allocDebug", 0, "Some debug output for memory allocations (without messing with normal debug level)")
340340
AddOption(debugMask, uint32_t, (1 << 18) - 1, "debugMask", 0, "Mask for debug output dumps to file")
341341
AddOption(debugLogSuffix, std::string, "", "debugSuffix", 0, "Suffix for debug log files with --debug 6")
342+
AddOption(debugDumpChecksum, bool, false, "", 0, "When using --debug 6, log only the checksum instead of writing the full dump to a file")
342343
AddOption(debugFileHexFloat, int32_t, -1, "", 0, "Use hex format to print floats to debug dump file")
343344
AddOption(debugCSV, std::string, "", "", 0, "CSV filename to append the benchmark results. Verbosity determined by parameter --debug.")
344345
AddOption(debugMarkdown, bool, false, "", 0, "Print the results of standlaone benchmarks in markdown format")

‎GPU/GPUTracking/Global/GPUChainTracking.cxx‎

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ using namespace o2::gpu;
6161
using namespace o2::tpc;
6262
using namespace o2::trd;
6363

64-
GPUChainTracking::GPUChainTracking(GPUReconstruction* rec, uint32_t maxTPCHits, uint32_t maxTRDTracklets) : GPUChain(rec), mIOPtrs(processors()->ioPtrs), mInputsHost(new GPUTrackingInputProvider), mInputsShadow(new GPUTrackingInputProvider), mClusterNativeAccess(new ClusterNativeAccess), mTriggerBuffer(new GPUTriggerOutputs), mMaxTPCHits(maxTPCHits), mMaxTRDTracklets(maxTRDTracklets), mDebugFile(new std::ofstream)
64+
GPUChainTracking::GPUChainTracking(GPUReconstruction* rec, uint32_t maxTPCHits, uint32_t maxTRDTracklets) : GPUChain(rec), mIOPtrs(processors()->ioPtrs), mInputsHost(new GPUTrackingInputProvider), mInputsShadow(new GPUTrackingInputProvider), mClusterNativeAccess(new ClusterNativeAccess), mTriggerBuffer(new GPUTriggerOutputs), mMaxTPCHits(maxTPCHits), mMaxTRDTracklets(maxTRDTracklets), mDebugFile(new std::ostream(nullptr))
6565
{
6666
ClearIOPointers();
6767
mFlatObjectsShadow.mChainTracking = this;
@@ -386,7 +386,17 @@ int32_t GPUChainTracking::Init()
386386

387387
if (GetProcessingSettings().debugLevel >= 6) {
388388
std::string filename = std::string(mRec->IsGPU() ? "GPU" : "CPU") + (mRec->slaveId() != -1 ? (std::string("_slave") + std::to_string(mRec->slaveId())) : std::string(mRec->slavesExist() ? "_master" : "")) + GetProcessingSettings().debugLogSuffix + ".out";
389-
mDebugFile->open(filename.c_str());
389+
390+
bool hashOnly = GetProcessingSettings().debugDumpChecksum;
391+
392+
std::streambuf* backing = nullptr;
393+
if (!hashOnly) {
394+
mDebugFileBuffer.open(filename.c_str(), std::ios::out);
395+
backing = &mDebugFileBuffer;
396+
}
397+
398+
mDebugFileStream = HashStreamBuf(hashOnly, backing);
399+
mDebugFile->rdbuf(&mDebugFileStream);
390400
if (GetProcessingSettings().debugFileHexFloat >= 1 || (GetProcessingSettings().debugFileHexFloat == -1 && GetProcessingSettings().deterministicGPUReconstruction)) {
391401
*mDebugFile << std::hexfloat;
392402
}
@@ -475,7 +485,12 @@ int32_t GPUChainTracking::Finalize()
475485
GetQA()->DrawQAHistograms();
476486
}
477487
if (GetProcessingSettings().debugLevel >= 6) {
478-
mDebugFile->close();
488+
mDebugFile->flush();
489+
mDebugFileBuffer.close();
490+
491+
if (GetProcessingSettings().debugDumpChecksum) {
492+
GPUInfo("Debug hash: %s", mDebugFileStream.hash().c_str());
493+
}
479494
}
480495
if (mCompressionStatistics) {
481496
mCompressionStatistics->Finish();

‎GPU/GPUTracking/Global/GPUChainTracking.h‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "GPUDataTypesIO.h"
2020
#include "GPUDataTypesConfig.h"
2121
#include "GPUCommonAlignedAlloc.h"
22+
#include "utils/HashStreamBuf.h"
2223
#include <atomic>
2324
#include <mutex>
2425
#include <functional>
@@ -286,7 +287,9 @@ class GPUChainTracking : public GPUChain
286287
uint32_t mMaxTRDTracklets = 0;
287288

288289
// Debug
289-
std::unique_ptr<std::ofstream> mDebugFile;
290+
std::filebuf mDebugFileBuffer;
291+
HashStreamBuf mDebugFileStream;
292+
std::unique_ptr<std::ostream> mDebugFile;
290293

291294
// Synchronization and Locks
292295
eventStruct* mEvents = nullptr;
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
/// \file HashStreamBuf.h
13+
/// \author Felix Weiglhofer
14+
/// \brief Stream buffer that supports on the fly hashing with an optional backing file buffer,
15+
// if we want to access the hash and file contents at the same time.
16+
17+
#include "Framework/SHA1.h"
18+
19+
#include <cstdint>
20+
#include <streambuf>
21+
#include <ostream>
22+
23+
class HashStreamBuf : public std::streambuf
24+
{
25+
public:
26+
HashStreamBuf() = default;
27+
28+
HashStreamBuf(bool doHash,
29+
std::streambuf* backing = nullptr)
30+
: mBacking(backing),
31+
mDoHash(doHash)
32+
{
33+
o2::framework::internal::SHA1Init(&mSHA1);
34+
}
35+
36+
// Returns the hash without modifying the current hashing state.
37+
std::string hash() const
38+
{
39+
auto copy = mSHA1;
40+
unsigned char digest[20];
41+
o2::framework::internal::SHA1Final(digest, &copy);
42+
43+
static constexpr char hex[] = "0123456789ABCDEF";
44+
std::string result;
45+
result.reserve(40);
46+
47+
for (unsigned char byte : digest) {
48+
result += hex[byte >> 4];
49+
result += hex[byte & 0x0f];
50+
}
51+
52+
return result;
53+
}
54+
55+
protected:
56+
std::streamsize xsputn(const char* data,
57+
std::streamsize size) override
58+
{
59+
if (size <= 0) {
60+
size = 0;
61+
}
62+
63+
if (mBacking) {
64+
// Only hash bytes that were successfully written
65+
// to the backing stream.
66+
size = mBacking->sputn(data, size);
67+
}
68+
69+
updateHash(data, size_t(size));
70+
return size;
71+
}
72+
73+
int_type overflow(int_type ch) override
74+
{
75+
if (traits_type::eq_int_type(ch, traits_type::eof()))
76+
return traits_type::not_eof(ch);
77+
78+
const char c = traits_type::to_char_type(ch);
79+
80+
if (mBacking) {
81+
const auto result = mBacking->sputc(c);
82+
83+
if (traits_type::eq_int_type(result,
84+
traits_type::eof())) {
85+
return traits_type::eof();
86+
}
87+
}
88+
89+
updateHash(&c, 1);
90+
91+
return ch;
92+
}
93+
94+
int sync() override
95+
{
96+
int s = 0;
97+
if (mBacking) {
98+
s = mBacking->pubsync();
99+
}
100+
return s;
101+
}
102+
103+
private:
104+
std::streambuf* mBacking = nullptr;
105+
o2::framework::internal::SHA1_CTX mSHA1;
106+
bool mDoHash = false;
107+
108+
void updateHash(const char* data, size_t size)
109+
{
110+
if (mDoHash) {
111+
o2::framework::internal::SHA1Update(&mSHA1, reinterpret_cast<const unsigned char*>(data), size);
112+
}
113+
}
114+
};

0 commit comments

Comments
 (0)