Skip to content

Commit

Permalink
#
Browse files Browse the repository at this point in the history
  • Loading branch information
tomilov committed Dec 11, 2021
1 parent aa92dfd commit 99d55d0
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 87 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
pg.txt
ref.txt
3 changes: 1 addition & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ set(CMAKE_CXX_EXTENSIONS ON)
foreach(target IN ITEMS "basic" "pb_ds" "lt" "oaph")
add_executable("${target}")
target_sources("${target}" PRIVATE "${target}.cpp" "io.hpp" "timer.hpp" "helpers.hpp")
target_compile_options("${target}" PRIVATE $<$<CXX_COMPILER_ID:Clang>:-march=native>)
target_compile_options("${target}" PRIVATE $<$<CXX_COMPILER_ID:GNU>:-march=native>)
target_compile_options("${target}" PRIVATE $<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:GNU>>:-march=native>)
if(target STREQUAL "pb_ds")
target_compile_options("${target}" PRIVATE $<$<CXX_COMPILER_ID:Clang>:-stdlib=libstdc++>)
target_link_options("${target}" PRIVATE $<$<CXX_COMPILER_ID:Clang>:-stdlib=libstdc++>)
Expand Down
10 changes: 4 additions & 6 deletions basic.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "helpers.hpp"
#include "io.hpp"
#include "timer.hpp"

#include <algorithm>
Expand Down Expand Up @@ -50,13 +49,13 @@ int main(int argc, char * argv[])
std::unordered_map<std::string_view, std::size_t> wordCounts;

auto isAlpha = [](char c) {
return std::isalpha(std::make_unsigned_t<char>(c));
return bool(std::isalpha(std::make_unsigned_t<char>(c)));
};
auto end = std::end(input);
auto beg = std::find_if(std::begin(input), end, isAlpha);
auto end = input.data() + input.size();
auto beg = std::find_if(input.data(), end, isAlpha);
while (beg != end) {
auto it = std::find_if(beg, end, std::not_fn(isAlpha));
++wordCounts[std::string_view(&*beg, std::distance(beg, it))];
++wordCounts[{beg, std::size_t(std::distance(beg, it))}];
beg = std::find_if(it, end, isAlpha);
}

Expand All @@ -83,7 +82,6 @@ int main(int argc, char * argv[])
for (auto wordCount : output) {
o << wordCount->second << ' ' << wordCount->first << '\n';
}

timer.report("write output");

return EXIT_SUCCESS;
Expand Down
37 changes: 18 additions & 19 deletions helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,18 @@
#error "!"
#endif

#if defined(__linux__) || defined(__APPLE__)
#define RED(s) "\e[3;31m" s "\e[0m"
#define GREEN(s) "\e[3;32m" s "\e[0m"
#define YELLOW(s) "\e[3;33m" s "\e[0m"
#define BLUE(s) "\e[3;34m" s "\e[0m"
#else
#define RED(s) s
#define GREEN(s) s
#define YELLOW(s) s
#define BLUE(s) s
#endif

#ifdef __cpp_lib_hardware_interference_size
inline constexpr std::size_t kHardwareConstructiveInterferenceSize =
std::hardware_constructive_interference_size;
Expand All @@ -33,33 +45,20 @@ inline constexpr std::size_t kHardwareConstructiveInterferenceSize = 64;
inline constexpr std::size_t kHardwareDestructiveInterferenceSize = 64;
#endif

inline void toLower(char * s, char * const end)
inline void toLower(char * beg, char * const end)
{
assert(s <= end);
for (; s < end; s += sizeof(__m128i)) {
__m128i string = _mm_load_si128(reinterpret_cast<const __m128i *>(s));
assert((reinterpret_cast<std::uintptr_t>(beg) % sizeof(__m128i)) == 0);
assert((reinterpret_cast<std::uintptr_t>(end) % sizeof(__m128i)) == 0);
for (; beg < end; beg += sizeof(__m128i)) {
__m128i string = _mm_load_si128(reinterpret_cast<const __m128i *>(beg));
__m128i lowercase = _mm_add_epi8(
string, _mm_and_si128(_mm_cmplt_epi8(string, _mm_set1_epi8('a')),
_mm_set1_epi8('a' - 'A')));
__m128i mask =
_mm_or_si128(_mm_cmplt_epi8(lowercase, _mm_set1_epi8('a')),
_mm_cmpgt_epi8(lowercase, _mm_set1_epi8('z')));
_mm_store_si128(reinterpret_cast<__m128i *>(s),
_mm_store_si128(reinterpret_cast<__m128i *>(beg),
_mm_andnot_si128(mask, lowercase));
}
if (s < end) {
__m128i string{};
auto c = reinterpret_cast<char *>(&string);
std::copy(s, end, c);
__m128i lowercase = _mm_add_epi8(
string, _mm_and_si128(_mm_cmplt_epi8(string, _mm_set1_epi8('a')),
_mm_set1_epi8('a' - 'A')));
__m128i mask =
_mm_or_si128(_mm_cmplt_epi8(lowercase, _mm_set1_epi8('a')),
_mm_cmpgt_epi8(lowercase, _mm_set1_epi8('z')));
string = _mm_andnot_si128(mask, lowercase);
for (; s < end; ++s) {
*s++ = *c++;
}
}
}
31 changes: 20 additions & 11 deletions io.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,26 @@
#include <cstdio>
#include <cstdlib>

#if defined(__linux__) || defined(__APPLE__)
#define RED(s) "\e[3;31m" s "\e[0m"
#define GREEN(s) "\e[3;32m" s "\e[0m"
#define YELLOW(s) "\e[3;33m" s "\e[0m"
#define BLUE(s) "\e[3;34m" s "\e[0m"
#else
#define RED(s) s
#define GREEN(s) s
#define YELLOW(s) s
#define BLUE(s) s
#endif
inline std::size_t readInput(char * inputBegin, std::size_t inputSize,
std::FILE * inputFile)
{
std::size_t readSize = std::fread(inputBegin, 1, inputSize, inputFile);
std::fprintf(stderr, "input size = %zu bytes\n", readSize);
if (!(readSize < inputSize)) {
std::fprintf(stderr, "input is too large\n");
return 0;
}

inputBegin += readSize;
while ((readSize % sizeof(__m128i)) != 0) {
*inputBegin++ = '\0';
if (++readSize > inputSize) {
std::fprintf(stderr, "input is too large\n");
return 0;
}
}
return readSize;
}

template<std::size_t bufferSize = 131072>
class OutputStream
Expand Down
24 changes: 7 additions & 17 deletions lt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace
alignas(__m128i) char input[1 << 29];
auto inputEnd = input;

struct alignas(kHardwareDestructiveInterferenceSize) TrieNode
struct TrieNode
{
uint32_t count = 0;
uint32_t children['z' - 'a' + 1] = {};
Expand Down Expand Up @@ -56,20 +56,12 @@ int main(int argc, char * argv[])

timer.report("open files");

{
std::size_t size =
std::fread(input, sizeof *input, std::extent_v<decltype(input)>,
inputFile.get());
if (!(size < std::extent_v<decltype(input)>)) {
std::fprintf(stderr, "input is too large\n");
return EXIT_FAILURE;
}
std::fprintf(stderr, "input size = %zu bytes\n", size);

inputEnd +=
((size + sizeof(__m128i) - 1) / sizeof(__m128i)) * sizeof(__m128i);
std::fill(input + size, inputEnd, '\0');
std::size_t readSize =
readInput(std::begin(input), std::size(input), inputFile.get());
if (readSize == 0) {
return EXIT_FAILURE;
}
inputEnd += readSize;
timer.report("read input");

toLower(input, inputEnd);
Expand Down Expand Up @@ -132,7 +124,6 @@ int main(int argc, char * argv[])
timer.report(YELLOW("sort words"));

OutputStream<> outputStream{outputFile.get()};

for (const auto & [count, word] : rank) {
if (!outputStream.print(count)) {
std::fprintf(stderr, "output failure");
Expand All @@ -151,8 +142,7 @@ int main(int argc, char * argv[])
return EXIT_FAILURE;
}
}

timer.report("output");
timer.report("write output");

return EXIT_SUCCESS;
}
17 changes: 6 additions & 11 deletions oaph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,17 +275,12 @@ int main(int argc, char * argv[])
return EXIT_FAILURE;
}

{
std::size_t size =
std::fread(input, sizeof *input, std::extent_v<decltype(input)>,
inputFile.get());
assert(size < std::extent_v<decltype(input)>);
std::fprintf(stderr, "input size = %zu bytes\n", size);

inputEnd +=
((size + sizeof(__m128i) - 1) / sizeof(__m128i)) * sizeof(__m128i);
std::fill(input + size, inputEnd, '\0');
std::size_t readSize =
readInput(std::begin(input), std::size(input), inputFile.get());
if (readSize == 0) {
return EXIT_FAILURE;
}
inputEnd += readSize;
timer.report("read input");

for (Chunk & chunk : hashTable) {
Expand Down Expand Up @@ -358,7 +353,7 @@ int main(int argc, char * argv[])
return EXIT_FAILURE;
}
}
timer.report("output");
timer.report("write output");

return EXIT_SUCCESS;
}
4 changes: 1 addition & 3 deletions pb_ds.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "helpers.hpp"
#include "io.hpp"
#include "timer.hpp"

#include <algorithm>
Expand Down Expand Up @@ -57,7 +56,7 @@ int main(int argc, char * argv[])
Trie trie;

auto isAlpha = [](char c) {
return std::isalpha(std::make_unsigned_t<char>(c));
return bool(std::isalpha(std::make_unsigned_t<char>(c)));
};
auto end = std::end(input);
auto beg = std::find_if(std::begin(input), end, isAlpha);
Expand Down Expand Up @@ -89,7 +88,6 @@ int main(int argc, char * argv[])
for (auto wordCount : output) {
o << wordCount->second << ' ' << wordCount->first << '\n';
}

timer.report("write output");

return EXIT_SUCCESS;
Expand Down
80 changes: 63 additions & 17 deletions run.bash
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,34 +1,80 @@
#! /usr/bin/bash

set -e
if ! [[ -x $1 ]]

if [[ ! -f pg.txt ]]
then
>&2 echo "No pg.txt in current directory"
exit 2
fi

if [[ ! -x $1 ]]
then
>&2 echo "Usage: bash run.bash <executable> <N>"
exit 1
>&2 echo "Usage: bash run.bash ABSOLUTE_PATH_TO_EXECUTABLE [N]"
exit 3
fi

if [[ $2 =~ [[:digit:]]+ ]]
if [[ ! $1 = /* ]]
then
N="$2"
>&2 echo "Value '$1' of the first parameter is not an absolute path"
exit 4
fi

if [[ $2 ]]
then
if [[ ! $2 =~ ^[[:digit:]]+$ ]]
then
>&2 echo "Value '$2' of the second parameter is not a number"
exit 5
fi
N=$2
else
N=1
fi

rsync pg.txt /tmp/
rsync ref.txt /tmp/out.txt
md5sum /tmp/out.txt >/tmp/out.txt.md5
if [[ ! -f pg.txt ]]
then
>&2 echo "File pg.txt is not found in current directory"
fi

if ! WORKSPACE="$( mktemp -d --tmpdir 'freq.XXXXXX' )"
then
>&2 echo "Unable to create temporary directory"
exit 7
fi

sudo find /sys/devices/system/cpu -name scaling_governor -exec sh -c 'echo performance >{}' ';'
sudo sh -c 'echo off >/sys/devices/system/cpu/smt/control ; tuna --cpus=1-7 --isolate'
NPROC="$( nproc )"

function on_exit {
sudo sh -c 'echo on >/sys/devices/system/cpu/smt/control ; tuna --cpus=0-15 --include'
sudo find /sys/devices/system/cpu -name scaling_governor -exec sh -c 'echo powersave >{}' ';'
set +e
if [[ $( cat /sys/devices/system/cpu/smt/control ) == "off" ]]
then
sudo sh -c 'echo on >/sys/devices/system/cpu/smt/control'
fi
sudo sh -c "tuna --cpus=0-$NPROC --include"
echo powersave | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
rm -r "$WORKSPACE"
}
trap on_exit EXIT

for (( i = 0 ; i < N; ++i ))
cp -a pg.txt "$WORKSPACE"
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
if [[ NPROC > 1 ]]
then
if [[ $( cat /sys/devices/system/cpu/smt/control ) == "on" ]]
then
sudo sh -c 'echo off >/sys/devices/system/cpu/smt/control'
fi
sudo sh -c "tuna --cpus=1-$NPROC --isolate"
fi

pushd "$WORKSPACE"
echo '850944413ba9fd1dbf2b9694abaa930d -' >out.txt.md5sum
for (( i = 0 ; i < N ; ++i ))
do
rm /tmp/out.txt
time LC_ALL="C" taskset --cpu-list 1-7 "$1" /tmp/pg.txt /tmp/out.txt
md5sum -c /tmp/out.txt.md5
time LC_ALL=C taskset --cpu-list 1-$NPROC "$1" pg.txt out.txt
>&2 echo -n
cat out.txt | md5sum --check out.txt.md5sum
rm out.txt
done

popd

0 comments on commit 99d55d0

Please sign in to comment.