Skip to content

Commit 9f981dd

Browse files
committed
merge bitcoin#27598: Add SHA256 implementation specific benchmarks
1 parent 306fa9a commit 9f981dd

File tree

3 files changed

+163
-23
lines changed

3 files changed

+163
-23
lines changed

src/bench/crypto_hash.cpp

Lines changed: 121 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <hash.h>
1616
#include <hash_x11.h>
1717
#include <random.h>
18+
#include <tinyformat.h>
1819
#include <uint256.h>
1920

2021
/* Number of bytes to hash per iteration */
@@ -38,13 +39,48 @@ static void SHA1(benchmark::Bench& bench)
3839
});
3940
}
4041

41-
static void SHA256(benchmark::Bench& bench)
42+
static void SHA256_STANDARD(benchmark::Bench& bench)
4243
{
44+
bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::STANDARD)));
4345
uint8_t hash[CSHA256::OUTPUT_SIZE];
4446
std::vector<uint8_t> in(BUFFER_SIZE,0);
4547
bench.batch(in.size()).unit("byte").run([&] {
4648
CSHA256().Write(in.data(), in.size()).Finalize(hash);
4749
});
50+
SHA256AutoDetect();
51+
}
52+
53+
static void SHA256_SSE4(benchmark::Bench& bench)
54+
{
55+
bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::USE_SSE4)));
56+
uint8_t hash[CSHA256::OUTPUT_SIZE];
57+
std::vector<uint8_t> in(BUFFER_SIZE,0);
58+
bench.batch(in.size()).unit("byte").run([&] {
59+
CSHA256().Write(in.data(), in.size()).Finalize(hash);
60+
});
61+
SHA256AutoDetect();
62+
}
63+
64+
static void SHA256_AVX2(benchmark::Bench& bench)
65+
{
66+
bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::USE_SSE4_AND_AVX2)));
67+
uint8_t hash[CSHA256::OUTPUT_SIZE];
68+
std::vector<uint8_t> in(BUFFER_SIZE,0);
69+
bench.batch(in.size()).unit("byte").run([&] {
70+
CSHA256().Write(in.data(), in.size()).Finalize(hash);
71+
});
72+
SHA256AutoDetect();
73+
}
74+
75+
static void SHA256_SHANI(benchmark::Bench& bench)
76+
{
77+
bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::USE_SSE4_AND_SHANI)));
78+
uint8_t hash[CSHA256::OUTPUT_SIZE];
79+
std::vector<uint8_t> in(BUFFER_SIZE,0);
80+
bench.batch(in.size()).unit("byte").run([&] {
81+
CSHA256().Write(in.data(), in.size()).Finalize(hash);
82+
});
83+
SHA256AutoDetect();
4884
}
4985

5086
static void SHA3_256_1M(benchmark::Bench& bench)
@@ -56,22 +92,92 @@ static void SHA3_256_1M(benchmark::Bench& bench)
5692
});
5793
}
5894

59-
static void SHA256_32b(benchmark::Bench& bench)
95+
static void SHA256_32b_STANDARD(benchmark::Bench& bench)
96+
{
97+
bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::STANDARD)));
98+
std::vector<uint8_t> in(32,0);
99+
bench.batch(in.size()).unit("byte").run([&] {
100+
CSHA256()
101+
.Write(in.data(), in.size())
102+
.Finalize(in.data());
103+
});
104+
SHA256AutoDetect();
105+
}
106+
107+
static void SHA256_32b_SSE4(benchmark::Bench& bench)
108+
{
109+
bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::USE_SSE4)));
110+
std::vector<uint8_t> in(32,0);
111+
bench.batch(in.size()).unit("byte").run([&] {
112+
CSHA256()
113+
.Write(in.data(), in.size())
114+
.Finalize(in.data());
115+
});
116+
SHA256AutoDetect();
117+
}
118+
119+
static void SHA256_32b_AVX2(benchmark::Bench& bench)
120+
{
121+
bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::USE_SSE4_AND_AVX2)));
122+
std::vector<uint8_t> in(32,0);
123+
bench.batch(in.size()).unit("byte").run([&] {
124+
CSHA256()
125+
.Write(in.data(), in.size())
126+
.Finalize(in.data());
127+
});
128+
SHA256AutoDetect();
129+
}
130+
131+
static void SHA256_32b_SHANI(benchmark::Bench& bench)
60132
{
133+
bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::USE_SSE4_AND_SHANI)));
61134
std::vector<uint8_t> in(32,0);
62135
bench.batch(in.size()).unit("byte").run([&] {
63136
CSHA256()
64137
.Write(in.data(), in.size())
65138
.Finalize(in.data());
66139
});
140+
SHA256AutoDetect();
141+
}
142+
143+
static void SHA256D64_1024_STANDARD(benchmark::Bench& bench)
144+
{
145+
bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::STANDARD)));
146+
std::vector<uint8_t> in(64 * 1024, 0);
147+
bench.batch(in.size()).unit("byte").run([&] {
148+
SHA256D64(in.data(), in.data(), 1024);
149+
});
150+
SHA256AutoDetect();
151+
}
152+
153+
static void SHA256D64_1024_SSE4(benchmark::Bench& bench)
154+
{
155+
bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::USE_SSE4)));
156+
std::vector<uint8_t> in(64 * 1024, 0);
157+
bench.batch(in.size()).unit("byte").run([&] {
158+
SHA256D64(in.data(), in.data(), 1024);
159+
});
160+
SHA256AutoDetect();
161+
}
162+
163+
static void SHA256D64_1024_AVX2(benchmark::Bench& bench)
164+
{
165+
bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::USE_SSE4_AND_AVX2)));
166+
std::vector<uint8_t> in(64 * 1024, 0);
167+
bench.batch(in.size()).unit("byte").run([&] {
168+
SHA256D64(in.data(), in.data(), 1024);
169+
});
170+
SHA256AutoDetect();
67171
}
68172

69-
static void SHA256D64_1024(benchmark::Bench& bench)
173+
static void SHA256D64_1024_SHANI(benchmark::Bench& bench)
70174
{
175+
bench.name(strprintf("%s using the '%s' SHA256 implementation", __func__, SHA256AutoDetect(sha256_implementation::USE_SSE4_AND_SHANI)));
71176
std::vector<uint8_t> in(64 * 1024, 0);
72177
bench.batch(in.size()).unit("byte").run([&] {
73178
SHA256D64(in.data(), in.data(), 1024);
74179
});
180+
SHA256AutoDetect();
75181
}
76182

77183
static void SHA512(benchmark::Bench& bench)
@@ -154,13 +260,22 @@ static void MuHashPrecompute(benchmark::Bench& bench)
154260

155261
BENCHMARK(BenchRIPEMD160);
156262
BENCHMARK(SHA1);
157-
BENCHMARK(SHA256);
263+
BENCHMARK(SHA256_STANDARD);
264+
BENCHMARK(SHA256_SSE4);
265+
BENCHMARK(SHA256_AVX2);
266+
BENCHMARK(SHA256_SHANI);
158267
BENCHMARK(SHA512);
159268
BENCHMARK(SHA3_256_1M);
160269

161-
BENCHMARK(SHA256_32b);
270+
BENCHMARK(SHA256_32b_STANDARD);
271+
BENCHMARK(SHA256_32b_SSE4);
272+
BENCHMARK(SHA256_32b_AVX2);
273+
BENCHMARK(SHA256_32b_SHANI);
162274
BENCHMARK(SipHash_32b);
163-
BENCHMARK(SHA256D64_1024);
275+
BENCHMARK(SHA256D64_1024_STANDARD);
276+
BENCHMARK(SHA256D64_1024_SSE4);
277+
BENCHMARK(SHA256D64_1024_AVX2);
278+
BENCHMARK(SHA256D64_1024_SHANI);
164279
BENCHMARK(FastRandom_32bit);
165280
BENCHMARK(FastRandom_1bit);
166281

src/crypto/sha256.cpp

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -579,9 +579,15 @@ bool AVXEnabled()
579579
} // namespace
580580

581581

582-
std::string SHA256AutoDetect()
582+
std::string SHA256AutoDetect(sha256_implementation::UseImplementation use_implementation)
583583
{
584584
std::string ret = "standard";
585+
Transform = sha256::Transform;
586+
TransformD64 = sha256::TransformD64;
587+
TransformD64_2way = nullptr;
588+
TransformD64_4way = nullptr;
589+
TransformD64_8way = nullptr;
590+
585591
#if defined(USE_ASM) && defined(HAVE_GETCPUID)
586592
bool have_sse4 = false;
587593
bool have_xsave = false;
@@ -592,16 +598,22 @@ std::string SHA256AutoDetect()
592598

593599
uint32_t eax, ebx, ecx, edx;
594600
GetCPUID(1, 0, eax, ebx, ecx, edx);
595-
have_sse4 = (ecx >> 19) & 1;
601+
if (use_implementation & sha256_implementation::USE_SSE4) {
602+
have_sse4 = (ecx >> 19) & 1;
603+
}
596604
have_xsave = (ecx >> 27) & 1;
597605
have_avx = (ecx >> 28) & 1;
598606
if (have_xsave && have_avx) {
599607
enabled_avx = AVXEnabled();
600608
}
601609
if (have_sse4) {
602610
GetCPUID(7, 0, eax, ebx, ecx, edx);
603-
have_avx2 = (ebx >> 5) & 1;
604-
have_x86_shani = (ebx >> 29) & 1;
611+
if (use_implementation & sha256_implementation::USE_AVX2) {
612+
have_avx2 = (ebx >> 5) & 1;
613+
}
614+
if (use_implementation & sha256_implementation::USE_SHANI) {
615+
have_x86_shani = (ebx >> 29) & 1;
616+
}
605617
}
606618

607619
#if defined(ENABLE_X86_SHANI) && !defined(BUILD_BITCOIN_INTERNAL)
@@ -637,27 +649,28 @@ std::string SHA256AutoDetect()
637649

638650
#if defined(ENABLE_ARM_SHANI) && !defined(BUILD_BITCOIN_INTERNAL)
639651
bool have_arm_shani = false;
640-
652+
if (use_implementation & sha256_implementation::USE_SHANI) {
641653
#if defined(__linux__)
642654
#if defined(__arm__) // 32-bit
643-
if (getauxval(AT_HWCAP2) & HWCAP2_SHA2) {
644-
have_arm_shani = true;
645-
}
655+
if (getauxval(AT_HWCAP2) & HWCAP2_SHA2) {
656+
have_arm_shani = true;
657+
}
646658
#endif
647659
#if defined(__aarch64__) // 64-bit
648-
if (getauxval(AT_HWCAP) & HWCAP_SHA2) {
649-
have_arm_shani = true;
650-
}
660+
if (getauxval(AT_HWCAP) & HWCAP_SHA2) {
661+
have_arm_shani = true;
662+
}
651663
#endif
652664
#endif
653665

654666
#if defined(MAC_OSX)
655-
int val = 0;
656-
size_t len = sizeof(val);
657-
if (sysctlbyname("hw.optional.arm.FEAT_SHA256", &val, &len, nullptr, 0) == 0) {
658-
have_arm_shani = val != 0;
659-
}
667+
int val = 0;
668+
size_t len = sizeof(val);
669+
if (sysctlbyname("hw.optional.arm.FEAT_SHA256", &val, &len, nullptr, 0) == 0) {
670+
have_arm_shani = val != 0;
671+
}
660672
#endif
673+
}
661674

662675
if (have_arm_shani) {
663676
Transform = sha256_arm_shani::Transform;

src/crypto/sha256.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,22 @@ class CSHA256
2626
CSHA256& Reset();
2727
};
2828

29+
namespace sha256_implementation {
30+
enum UseImplementation : uint8_t {
31+
STANDARD = 0,
32+
USE_SSE4 = 1 << 0,
33+
USE_AVX2 = 1 << 1,
34+
USE_SHANI = 1 << 2,
35+
USE_SSE4_AND_AVX2 = USE_SSE4 | USE_AVX2,
36+
USE_SSE4_AND_SHANI = USE_SSE4 | USE_SHANI,
37+
USE_ALL = USE_SSE4 | USE_AVX2 | USE_SHANI,
38+
};
39+
}
40+
2941
/** Autodetect the best available SHA256 implementation.
3042
* Returns the name of the implementation.
3143
*/
32-
std::string SHA256AutoDetect();
44+
std::string SHA256AutoDetect(sha256_implementation::UseImplementation use_implementation = sha256_implementation::USE_ALL);
3345

3446
/** Compute multiple double-SHA256's of 64-byte blobs.
3547
* output: pointer to a blocks*32 byte output buffer

0 commit comments

Comments
 (0)