message: Print out the contents of buffers passed to KernelThunk at VLOG(100)
  Note that this will be painful unless the buffers are tiny.
diff: @@ -69,6 +69,23 @@ void KernelThunk::SetLaunchDimensions(const LaunchDimensions& launch_dims) {
  launch_dimensions_ = launch_dims;
  }
  +static void PrintBufferContents(
  + se::Stream* stream, absl::Span<const se::DeviceMemoryBase> buffer_args) {
  + int input_idx = 0;
  + for (const se::DeviceMemoryBase& buf : buffer_args) {
  + auto host_buffer = absl::make_unique<char[]>(buf.size());
  + CHECK(stream->ThenMemcpy(host_buffer.get(), buf, buf.size()).ok());
  + CHECK(stream->BlockHostUntilDone().ok());
  +
  + std::string buffer_contents;
  + for (int i = 0; i < buf.size(); i++) {
  + absl::StrAppendFormat(&buffer_contents, "%x ",
  + static_cast<unsigned>(host_buffer[i]));
  + }
  + VLOG(100) << "BUF(" << input_idx++ << ") = " << buffer_contents;
  + }
  +}
  +
  Status KernelThunk::ExecuteOnStream(const ExecuteParams& params) {
  // Load the kernel.
  se::StreamExecutor* executor = params.stream->parent();
  @@ -93,6 +110,11 @@ Status KernelThunk::ExecuteOnStream(const ExecuteParams& params) {
  << buf.size() << "B)";
  buffer_args.push_back(buf);
  }
  +
  + if (VLOG_IS_ON(100)) {
  + PrintBufferContents(params.stream, buffer_args);
  + }
  +
  auto op_profiler =
  params.profiler->MakeScopedInstructionProfiler(hlo_instruction());
  return ExecuteKernelOnStream(*kernel, buffer_args,
  