Skip to content

Commit

Permalink
Merge branch 'chacha-main'
Browse files Browse the repository at this point in the history
* chacha-main:
  CHACHA: Makefile: build and run chacha tests from main.cc
  CHACHA: main.cc: move main() and benchmark logic here
  CHACHA: chacha.cc: remove main()

Signed-off-by: Tim Janik <[email protected]>
  • Loading branch information
tim-janik committed Dec 3, 2023
2 parents 5425f93 + cfcfc66 commit dd7cf3f
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 83 deletions.
4 changes: 2 additions & 2 deletions chacha/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ CXX := $(if $(MAYBE_CLANG), $(MAYBE_CLANG), $(CXX))
OPTIMIZE := -O3 -march=native

# == chacha ==
chacha: chacha.cc Makefile
chacha: main.cc Makefile
$(CXX) -std=gnu++17 -Wall $(OPTIMIZE) $< -o chacha
chacha: chacha.hh
chacha: chacha.cc chacha.hh
clean: ; rm -f ./chacha
all: chacha

Expand Down
81 changes: 0 additions & 81 deletions chacha/chacha.cc
Original file line number Diff line number Diff line change
Expand Up @@ -199,84 +199,3 @@ chacha_stream_tests (uint64_t nonce, const std::array<uint8_t, 32> &key)
printf (" OK (AVX2 validation)\n");
}
}

static uint64_t
generate_bytes (uint64_t nonce, const std::array<uint8_t, 32> &key, const uint64_t nbytes, const unsigned rounds, unsigned kind)
{
const unsigned N = std::min (nbytes, 64 * 1024 * 1024ul);
std::vector<uint8_t> buffer (N, 0);
std::array<uint32_t, 16> state;
ChaCha::key_setup (state, 256, key, nonce);
size_t total;
for (total = 0; total < nbytes; /**/) {
uint8_t *start = buffer.data(), *last = start + N - 64 * ChaCha::avx_blocks;
while (start < last)
start += ChaCha::generate_blocks (state, N, nullptr, start, rounds, kind);
fwrite (buffer.data(), start - buffer.data(), 1, stdout);
total += start - buffer.data();
}
return total;
}

/// Return the current time as uint64 in µseconds.
static uint64_t
timestamp_realtime ()
{
struct timespec tp = { 0, 0 };
if (clock_gettime (CLOCK_REALTIME, &tp) >= 0)
return tp.tv_sec * 1000000ULL + tp.tv_nsec / 1000;
assert (!"clock_gettime fail");
}

int
main (int argc, const char *argv[])
{
// ChaCha8 should be fine for CSPRNG purposes: https://github.com/rust-random/rand/issues/932
std::array<uint8_t, 32> key{};
getrandom (key.data(), key.size(), GRND_NONBLOCK);
uint64_t nonce = timestamp_realtime();

double streamlen = 0;
unsigned kind = ~0; // ALU
for (size_t i = 1; i < argc; i++)
if (0 == strcasecmp (argv[i], "--check")) {
chacha_tests();
chacha_stream_tests (nonce, key);
return 0;
} else if (0 == strcasecmp (argv[i], "--sse"))
kind = 2; // SSE
else if (0 == strcasecmp (argv[i], "--alu"))
kind = 1; // ALU
else if (0 == strcasecmp (argv[i], "--avx"))
kind = 4; // AVX2
else if (0 == strcasecmp (argv[i], "--seed") && i+1 < argc) {
nonce = strtoull (argv[++i], nullptr, 0);
key = std::array<uint8_t, 32>{};
} else if (0 == strcmp (argv[i], "--bench") && i+1 < argc) {
const char *arg = argv[++i];
char *u = nullptr;
streamlen = strtoull (arg, &u, 0);
if (u && u[0])
switch (u[0])
{
case 'K': streamlen *= 1024; break;
case 'M': streamlen *= 1024 * 1024; break;
case 'G': streamlen *= 1024 * 1024 * 1024; break;
case 'T': streamlen *= 1024 * 1024 * 1024 * 1024ull; break;
}
}

if (streamlen > 0) {
streamlen = std::min (streamlen, 0x1p+63); // 2^63 = 9223372036854775808
dprintf (2, "BENCH: %zu Bytes\n", size_t (streamlen));
auto t1 = timestamp_realtime();
const size_t total = generate_bytes (nonce, key, uint64_t (streamlen), 8, kind);
auto t2 = timestamp_realtime();
dprintf (2, " %.3f msecs (%zu Bytes), %f GB/sec\n", (t2 - t1) / 1000.0, total, total * (1000000.0 / (1024*1024*1024)) / (t2 - t1));
}
else
generate_bytes (nonce, key, ~uint64_t (0), 8, kind);

return 0;
}
// clang++ -std=gnu++17 -Wall -march=native -O3 chacha.cc -o chacha && ./chacha | dieharder -a -g 200
81 changes: 81 additions & 0 deletions chacha/main.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Licensed CC0 Public Domain

#include <chrono> // std::chrono
#include <sys/random.h>

#include "chacha.cc"

/// Return the current time as uint64 in nanoseconds.
extern inline uint64_t timestamp_nsecs() { return std::chrono::steady_clock::now().time_since_epoch().count(); }

static uint64_t
generate_bytes (uint64_t nonce, const std::array<uint8_t, 32> &key, const uint64_t nbytes, const unsigned rounds, unsigned kind, FILE *fout)
{
const unsigned N = std::min (nbytes, 64 * 1024 * 1024ul);
std::vector<uint8_t> buffer (N, 0);
std::array<uint32_t, 16> state;
ChaCha::key_setup (state, 256, key, nonce);
size_t total;
for (total = 0; total < nbytes; /**/) {
uint8_t *start = buffer.data(), *last = start + N - 64 * ChaCha::avx_blocks;
while (start < last)
start += ChaCha::generate_blocks (state, N, nullptr, start, rounds, kind);
if (fout)
fwrite (buffer.data(), start - buffer.data(), 1, fout);
total += start - buffer.data();
}
return total;
}

int
main (int argc, const char *argv[])
{
// ChaCha8 should be fine for CSPRNG purposes: https://github.com/rust-random/rand/issues/932
std::array<uint8_t, 32> key{};
auto const dummy1 [[maybe_unused]] = getrandom (key.data(), key.size(), GRND_NONBLOCK);
uint64_t nonce = timestamp_nsecs();

double streamlen = 0;
unsigned kind = ~0; // ALU
for (int i = 1; i < argc; i++)
if (0 == strcasecmp (argv[i], "--check")) {
chacha_tests();
chacha_stream_tests (nonce, key);
return 0;
} else if (0 == strcasecmp (argv[i], "--sse"))
kind = 2; // SSE
else if (0 == strcasecmp (argv[i], "--alu"))
kind = 1; // ALU
else if (0 == strcasecmp (argv[i], "--avx"))
kind = 4; // AVX2
else if (0 == strcasecmp (argv[i], "--seed") && i+1 < argc) {
nonce = strtoull (argv[++i], nullptr, 0);
key = std::array<uint8_t, 32>{};
} else if (0 == strcmp (argv[i], "--bench")) {
const char *arg = i+1 < argc ? argv[++i] : "1G";
char *u = nullptr;
streamlen = strtoull (arg, &u, 0);
if (u && u[0])
switch (u[0])
{
case 'K': streamlen *= 1024; break;
case 'M': streamlen *= 1024 * 1024; break;
case 'G': streamlen *= 1024 * 1024 * 1024; break;
case 'T': streamlen *= 1024 * 1024 * 1024 * 1024ull; break;
}
}

if (streamlen > 0) {
streamlen = std::min (streamlen, 0x1p+63); // 2^63 = 9223372036854775808
dprintf (2, "BENCH: %zu Bytes\n", size_t (streamlen));
auto t1 = timestamp_nsecs();
const size_t total = generate_bytes (nonce, key, uint64_t (streamlen), 8, kind, nullptr);
auto t2 = timestamp_nsecs();
dprintf (2, " %.3f msecs (%zu Bytes), %f GB/sec\n", (t2 - t1) / 1000000.0, total, total * (1000000000.0 / (1024*1024*1024)) / (t2 - t1));
}
else
generate_bytes (nonce, key, ~uint64_t (0), 8, kind, stdout);

return 0;
}
// clang++ -std=gnu++17 -Wall -march=native -O3 main.cc -o chacha && ./chacha | dieharder -a -g 200

0 comments on commit dd7cf3f

Please sign in to comment.