Newer
Older
// SPDX-License-Identifier: LGPL-3.0-or-later
// Copyright © 2020-2022 Florian Schmaus
#include <array>
#include <atomic>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <random>
#include "Common.hpp" // for ALIGN_TO_CACHE_LINE
#include "CountingPrivateSemaphore.hpp" // for CPS
#include "Fiber.hpp" // for Fiber, Fiber::NOT_AFFINE
#include "Runtime.hpp" // for Runtime
#include "emper-common.h" // for UNUSED_ARG, workeraffini...
#include "lib/template_util.hpp"
#include "strategies/laws/LawsStrategy.hpp"
namespace tu = emper::lib::template_util;
static const unsigned int ROUND_COUNT = 10;
static const unsigned int FIBER_LOOPS = 10;
static const unsigned int PAYLOAD_COUNT = 4096;
using FiberData = struct ALIGN_TO_CACHE_LINE {
// 4096 * 8 byte (64 bit) = 32 KiB = L1 cache size of most systems
std::array<uint64_t, PAYLOAD_COUNT> payload;
using AlignedWorkerAffinity = struct ALIGN_TO_CACHE_LINE { workeraffinity_t affinity; };
static void fiberFun(void* voidFiberData) {
auto* fiberData = static_cast<FiberData*>(voidFiberData);
std::random_device randomDevice;
std::mt19937_64 randomGenerator(randomDevice());
std::uniform_int_distribution<unsigned long long> randomDistribution(0, UINT64_MAX);
for (unsigned int i = 0; i < FIBER_LOOPS; ++i) {
unsigned long long r = randomDistribution(randomGenerator);
}
}
fiberData->cps->signalAndExit();
}
static void alphaFun() {
Runtime* runtime = Runtime::getRuntime();
const unsigned int FIBER_COUNT = runtime->getWorkerCount() + 3;
auto* affinities = new AlignedWorkerAffinity[FIBER_COUNT];
auto* fiberData = new FiberData[FIBER_COUNT];
for (unsigned int i = 0; i < FIBER_COUNT; ++i) {
FiberData& currentFiberData = fiberData[i];
auto& payload = currentFiberData.payload;
memset(payload.data(), 0, tu::getSize(payload));
currentFiberData.fiberNum = i;
currentFiberData.cps = nullptr;
affinities[i].affinity = Fiber::NOT_AFFINE;
}
for (unsigned int round = 0; round < ROUND_COUNT; ++round) {
CPS cps(FIBER_COUNT);
for (unsigned int i = 0; i < FIBER_COUNT; ++i) {
FiberData* myFiberData = &fiberData[i];
myFiberData->cps = &cps;
Fiber* fiber = Fiber::from(&fiberFun, myFiberData, &affinities[i].affinity);
runtime->schedule(*fiber);
}
cps.wait();
}
std::atomic<uint64_t> finalResult(0);
CPS cps(FIBER_COUNT);
for (unsigned int i = 0; i < FIBER_COUNT; ++i) {
FiberData* myFiberData = &fiberData[i];
myFiberData->cps = &cps;
Fiber* fiber = Fiber::from(
[myFiberData, &finalResult]() {
uint64_t mySum = 0;
for (unsigned long i : myFiberData->payload) {
mySum += i;
}
finalResult += mySum;
myFiberData->cps->signalAndExit();
},
&affinities[i].affinity);
delete[] fiberData;
delete[] affinities;
std::cerr << "Result: " << finalResult << std::endl;
exit(EXIT_SUCCESS);
}
auto main(UNUSED_ARG int args, UNUSED_ARG char* argv[]) -> int {
Runtime runtime(LawsStrategy::getFactory());
Fiber* alphaFiber = Fiber::from(&alphaFun);
runtime.scheduleFromAnywhere(*alphaFiber);
return EXIT_FAILURE;