Skip to content

Commit ab9f0f5

Browse files
committed
Optimize hashing of program source for the purpose of offline caching
1 parent 1076807 commit ab9f0f5

File tree

3 files changed

+46
-35
lines changed

3 files changed

+46
-35
lines changed

vexcl/backend/common.hpp

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -182,20 +182,30 @@ inline std::string program_binaries_path(const std::string &hash, bool create =
182182
return dir + path_delim();
183183
}
184184

185-
/// Returns SHA1 hash of the string parameter.
186-
inline std::string sha1(const std::string &src) {
187-
boost::uuids::detail::sha1 sha1;
188-
sha1.process_bytes(src.c_str(), src.size());
189-
190-
unsigned int hash[5];
191-
sha1.get_digest(hash);
192-
193-
std::ostringstream buf;
194-
for(int i = 0; i < 5; ++i)
195-
buf << std::hex << std::setfill('0') << std::setw(8) << hash[i];
196-
197-
return buf.str();
198-
}
185+
/// SHA1 hasher.
186+
class sha1_hasher {
187+
public:
188+
sha1_hasher(const std::string &s = "") {
189+
if (!s.empty()) (*this)(s);
190+
}
191+
192+
void operator()(const std::string &s) {
193+
h.process_bytes(s.c_str(), s.size());
194+
}
195+
196+
operator std::string() {
197+
unsigned int digest[5];
198+
h.get_digest(digest);
199+
200+
std::ostringstream buf;
201+
for(int i = 0; i < 5; ++i)
202+
buf << std::hex << std::setfill('0') << std::setw(8) << digest[i];
203+
204+
return buf.str();
205+
}
206+
private:
207+
boost::uuids::detail::sha1 h;
208+
};
199209

200210
} // namespace vex
201211

vexcl/backend/cuda/compiler.hpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,17 @@ inline CUmodule build_sources(
6363

6464
queue.context().set_current();
6565

66+
sha1_hasher sha1(source);
67+
68+
sha1(queue.device().name());
69+
sha1(options);
70+
6671
auto cc = queue.device().compute_capability();
67-
std::ostringstream fullsrc;
68-
fullsrc << "// Device: " << queue.device().name() << "\n"
69-
<< "// CC: " << std::get<0>(cc) << "." << std::get<1>(cc) << "\n"
70-
<< "// options: " << options << "\n"
71-
<< source;
72+
sha1(std::to_string(std::get<0>(cc)) + std::to_string(std::get<1>(cc)));
73+
74+
std::string hash = static_cast<std::string>(sha1);
7275

7376
// Write source to a .cu file
74-
std::string hash = sha1( fullsrc.str() );
7577
std::string basename = program_binaries_path(hash, true) + "kernel";
7678
std::string ptxfile = basename + ".ptx";
7779

@@ -81,20 +83,19 @@ inline CUmodule build_sources(
8183

8284
{
8385
std::ofstream f(basename + ".cu");
84-
f << fullsrc.str();
86+
f << source;
8587
}
8688

8789
// Compile the source to ptx.
8890
std::ostringstream cmdline;
89-
auto cc = queue.device().compute_capability();
9091
cmdline
9192
<< "nvcc -ptx -O3"
9293
<< " -arch=sm_" << std::get<0>(cc) << std::get<1>(cc)
9394
<< " " << options
9495
<< " -o " << ptxfile << " " << cufile;
9596
if (0 != system(cmdline.str().c_str()) ) {
9697
#ifndef VEXCL_SHOW_KERNELS
97-
std::cerr << fullsrc.str() << std::endl;
98+
std::cerr << source << std::endl;
9899
#endif
99100

100101
vex::detail::print_backtrace();

vexcl/backend/opencl/compiler.hpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ namespace opencl {
4949

5050
/// Saves program binaries for future reuse.
5151
inline void save_program_binaries(
52-
const std::string &hash, const cl::Program &program, const std::string &source
52+
const std::string &hash, const cl::Program &program
5353
)
5454
{
5555
// Prevent writing to the same file by several threads at the same time.
@@ -67,8 +67,6 @@ inline void save_program_binaries(
6767
bfile.write((char*)&sizes[0], sizeof(size_t));
6868
bfile.write(binaries[0], sizes[0]);
6969
delete[] binaries[0];
70-
71-
bfile << "\n" << source << "\n";
7270
}
7371

7472
/// Tries to read program binaries from file cache.
@@ -133,12 +131,14 @@ inline cl::Program build_sources(
133131

134132
#ifdef VEXCL_CACHE_KERNELS
135133
// Get unique (hopefully) hash string for the kernel.
136-
std::ostringstream fullsrc;
134+
sha1_hasher sha1(source);
135+
136+
sha1(cl::Platform(device[0].getInfo<CL_DEVICE_PLATFORM>()).getInfo<CL_PLATFORM_NAME>());
137+
sha1(device[0].getInfo<CL_DEVICE_NAME>());
138+
sha1(compile_options);
137139

138-
fullsrc
139-
<< "// Platform: " << cl::Platform(device[0].getInfo<CL_DEVICE_PLATFORM>()).getInfo<CL_PLATFORM_NAME>()
140-
<< "\n// Device: " << device[0].getInfo<CL_DEVICE_NAME>()
141-
<< "\n// Compiler: "
140+
std::ostringstream compiler_tag;
141+
compiler_tag
142142
#if defined(_MSC_VER)
143143
<< "MSC " << _MSC_VER
144144
#elif defined(__clang__)
@@ -148,10 +148,10 @@ inline cl::Program build_sources(
148148
#else
149149
<< "unknown"
150150
#endif
151-
<< "\n// options: " << compile_options
152-
<< "\n" << source;
151+
;
152+
sha1(compiler_tag.str());
153153

154-
std::string hash = sha1( fullsrc.str() );
154+
std::string hash = static_cast<std::string>(sha1);
155155

156156
// Try to get cached program binaries:
157157
try {
@@ -181,7 +181,7 @@ inline cl::Program build_sources(
181181

182182
#ifdef VEXCL_CACHE_KERNELS
183183
// Save program binaries for future reuse:
184-
save_program_binaries(hash, program, fullsrc.str());
184+
save_program_binaries(hash, program);
185185
#endif
186186

187187
return program;

0 commit comments

Comments
 (0)