Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.15)
project(XIA2tree VERSION 1.2.1 LANGUAGES C CXX)
project(XIA2tree VERSION 1.3.0 LANGUAGES C CXX)

# Default to the project version when git information is unavailable
set(FULL_VERSION "${PROJECT_VERSION}")
Expand All @@ -18,7 +18,7 @@ CPMAddPackage("gh:TheLartians/PackageProject.cmake@1.13.0")
find_package(Threads REQUIRED)
find_package(ROOT REQUIRED COMPONENTS RIO Tree Hist)

CPMAddPackage("gh:vetlewi/Histogram@1.3.3")
CPMAddPackage("gh:vetlewi/Histogram@2.0.0")

add_library(structopt INTERFACE)
target_include_directories(structopt
Expand Down Expand Up @@ -88,6 +88,7 @@ add_library(XIAfuncs
${CMAKE_CURRENT_SOURCE_DIR}/src/Tasks/Buffer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Tasks/Calibrator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Tasks/MemoryMap.cpp
#${CMAKE_CURRENT_SOURCE_DIR}/src/Tasks/Sort.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Tasks/MTSort.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Tasks/Splitter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Tasks/Trigger.cpp
Expand Down Expand Up @@ -125,19 +126,23 @@ target_include_directories(UserSort

target_link_libraries(UserSort PRIVATE XIAfuncs)

set_target_properties(UserSort PROPERTIES CXX_STANDARD 17)
set_target_properties(UserSort PROPERTIES CXX_STANDARD 20)
set_target_properties(UserSort PROPERTIES POSITION_INDEPENDENT_CODE ON)
add_library(OCL::UserSort ALIAS UserSort)

add_library(ParticleCoincidenceSort MODULE ParticleCoincidenceSort.cpp)
set_target_properties(ParticleCoincidenceSort PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_link_libraries(ParticleCoincidenceSort PUBLIC OCL::UserSort)

add_library(Co60CoincidenceSort MODULE Co60_coincidence_sort.cpp)
set_target_properties(Co60CoincidenceSort PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_link_libraries(Co60CoincidenceSort PUBLIC OCL::UserSort)

add_library(TimingInvestigation MODULE TimingInvestigation.cpp)
set_target_properties(TimingInvestigation PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_link_libraries(TimingInvestigation PUBLIC OCL::UserSort)

set_target_properties(XIAfuncs PROPERTIES CXX_STANDARD 17)
set_target_properties(XIAfuncs PROPERTIES CXX_STANDARD 20)
target_link_libraries(XIAfuncs
PUBLIC
OCL::Histogram
Expand All @@ -157,7 +162,7 @@ target_link_libraries(Co60CoincidenceSort PRIVATE OCL::Histogram XIAfuncs UserSo
target_link_libraries(TimingInvestigation PRIVATE OCL::Histogram XIAfuncs UserSort)

add_executable(XIA2tree main.cpp)
set_target_properties(XIA2tree PROPERTIES CXX_STANDARD 17)
set_target_properties(XIA2tree PROPERTIES CXX_STANDARD 20)
target_link_libraries(XIA2tree PRIVATE OCL::Histogram UserSort XIAfuncs readerwriterqueue concurrentqueue)
add_dependencies(XIA2tree ParticleCoincidenceSort)

Expand Down
8 changes: 0 additions & 8 deletions Co60_coincidence_sort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ class Co60CoincidenceSort : public UserSort
public:
Co60CoincidenceSort(ThreadSafeHistograms *hist);
void FillEvent(const Triggered_event &event) override;
void Flush() override;
};


Expand Down Expand Up @@ -69,11 +68,4 @@ void Co60CoincidenceSort::FillEvent(const Triggered_event &event)
}
}

}

void Co60CoincidenceSort::Flush()
{
gamgam.force_flush();
time_labr_fine.force_flush();
timediff_de.force_flush();
}
17 changes: 0 additions & 17 deletions ParticleCoincidenceSort.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ class ParticleCoincidence : public UserSort
ParticleCoincidence(ThreadSafeHistograms *hist, const OCL::UserConfiguration *user_config);
~ParticleCoincidence() override = default;
void FillEvent(const Triggered_event &event) override;
void Flush() override;

};

Expand Down Expand Up @@ -151,20 +150,4 @@ void ParticleCoincidence::FillEvent(const Triggered_event &event)
}
}
}

}

void ParticleCoincidence::Flush()
{
de_thickness.force_flush();
particle_energy.force_flush();
excitation_energy.force_flush();
exgam.force_flush();
exgam_full.force_flush();
gamgam.force_flush();
part_gamgam.force_flush();
sum_ex_gam.force_flush();
gam_part_time.force_flush();
std::cout << "Average thickness: " << thickness << std::endl;
std::cout << "Counts: " << counts << std::endl;
}
14 changes: 0 additions & 14 deletions TimingInvestigation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ class TimingInvestigation : public UserSort
public:
TimingInvestigation(ThreadSafeHistograms *hist);
void FillEvent(const Triggered_event &event) override;
void Flush() override;

};

Expand Down Expand Up @@ -352,17 +351,4 @@ void TimingInvestigation::FillEvent(const Triggered_event &event)
}*/
}
}
}

void TimingInvestigation::Flush()
{
gamgam_time.force_flush();
for ( auto &m : de_time_energy )
m.force_flush();
for ( auto &m : e_time_energy )
m.force_flush();
range.force_flush();
gamgam_satelite.force_flush();
gamgam_prompt.force_flush();
gamgam_prompt_satelite.force_flush();
}
2 changes: 1 addition & 1 deletion include/Format/entry.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ struct Entry_t {
bool cfdfail;

// QDC values
std::vector<uint32_t> qdc{0};
std::array<uint32_t, 8> qdc{0};

// Traces
std::vector<uint16_t> trace{0};
Expand Down
24 changes: 23 additions & 1 deletion include/Format/xiaformat.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#ifndef XIAFORMAT_H
#define XIAFORMAT_H
#include <array>

struct XIA_event_4_t;
struct XIA_event_6_t;
Expand Down Expand Up @@ -118,7 +119,7 @@ struct XIA_event_18_t : public XIA_base_t {
uint16_t trace[];
};

inline std::vector<uint32_t> getQDC(const XIA_base_t *event) {
/*inline std::vector<uint32_t> getQDC(const XIA_base_t *event) {
switch ( event->headerLen ) {
case 12 :
return {reinterpret_cast<const XIA_event_12_t *>(event)->qdc,
Expand All @@ -135,6 +136,27 @@ inline std::vector<uint32_t> getQDC(const XIA_base_t *event) {
default:
return std::vector<uint32_t>(0);
}
}*/

inline std::array<uint32_t, 8> getQDC(const XIA_base_t *event) {
const uint32_t* qdc = nullptr;
switch ( event->headerLen ) {
case 12 :
qdc = reinterpret_cast<const XIA_event_12_t *>(event)->qdc;
break;
case 14 :
qdc = reinterpret_cast<const XIA_event_14_t *>(event)->qdc;
break;
case 16 :
qdc = reinterpret_cast<const XIA_event_16_t *>(event)->qdc;
break;
case 18 :
qdc = reinterpret_cast<const XIA_event_18_t *>(event)->qdc;
break;
default:
return {};
}
return {qdc[0], qdc[1], qdc[2], qdc[3], qdc[4], qdc[5], qdc[6], qdc[7]};
}

inline std::vector<uint16_t> getTrace(const XIA_base_t *event) {
Expand Down
3 changes: 2 additions & 1 deletion include/RootInterface/TTreeManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <TFile.h>
#include <TTree.h>
#include <Compression.h>

#include <entry.h>
#include <event.h>
Expand All @@ -28,7 +29,7 @@ namespace Task {
bool cfdfail;
double cfdcorr;
unsigned short idx; //!< Index in list of detectors that the trigger corresponds to.
std::vector<uint32_t> qdc;
std::array<uint32_t, 8> qdc;

public:
explicit TriggerEntry(TTree &tree);
Expand Down
8 changes: 4 additions & 4 deletions include/Tasks/MTSort.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,13 @@ namespace Task {
class MTSort : public Base
{
private:
TEventQueue_t &input_queue;
MTEventQueue_t &input_queue;
HistManager hm;
const OCL::UserConfiguration& userConfig;
std::unique_ptr<ROOT::TTreeManager> tree;

public:
MTSort(TEventQueue_t &input, ThreadSafeHistograms &histograms, const OCL::UserConfiguration &config,
MTSort(MTEventQueue_t &input, ThreadSafeHistograms &histograms, const OCL::UserConfiguration &config,
const char *tree_name = nullptr, const char *user_sort = nullptr);
~MTSort() override = default;
void Run() override;
Expand All @@ -118,7 +118,7 @@ namespace Task {
class Sorters
{
private:
TEventQueue_t &input_queue;
MTEventQueue_t &input_queue;
ThreadSafeHistograms histograms;
std::vector<MTSort *> sorters;
const OCL::UserConfiguration &user_config;
Expand All @@ -127,7 +127,7 @@ namespace Task {
std::vector<std::string> tree_files; //! To be returned to the user when everything is said and done.

public:
Sorters(TEventQueue_t &input, OCL::UserConfiguration &config, const char *tree_name = nullptr, const char *user_sort = nullptr);
Sorters(MTEventQueue_t &input, OCL::UserConfiguration &config, const char *tree_name = nullptr, const char *user_sort = nullptr);
~Sorters();
void flush();
Histograms &GetHistograms(){
Expand Down
62 changes: 13 additions & 49 deletions include/Tasks/Queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,64 +5,28 @@
#ifndef QUEUE_H
#define QUEUE_H

#include <atomic>

#include <Format/entry.h>
#include <Format/event.h>
#include <Format/xiaformat.h>

#include <readerwriterqueue.h>
#include <blockingconcurrentqueue.h>
#include <readerwritercircularbuffer.h>
#include <concurrentqueue.h>

namespace Task {

template<typename T>
struct QueueWrapper
{
T queue;
std::atomic<bool> done;

template<typename U>
inline bool try_enqueue(U const &u){ return queue.try_enqueue(u); }

template<typename U>
inline bool try_enqueue(U &&u){ return queue.try_enqueue(u); }

template<typename U>
inline auto enqueue(U const &u){ return queue.enqueue(u); }
#include "SPSCQueue.h"
#include "SPMCQueue.h"

template<typename U>
inline auto enqueue(U &&u){ return queue.enqueue(u); }

template<typename U>
inline void wait_enqueue(U const &u){ queue.wait_enqueue(u); }

template<typename U>
inline void wait_enqueue(U &&u){ queue.wait_enqueue(u); }

/*template <typename U, typename V>
inline bool wait_enqueue_timed(U &u, V const &v){ return queue.wait_enqueue(u); }

template <typename U, typename V>
inline bool wait_enqueue_timed(U &&u, V const &v){ return queue.wait_enqueue(u); }
#include <blockingconcurrentqueue.h>

template<typename U, typename V>
inline bool wait_dequeue_timed(U &u, V const &v){ return queue.wait_dequeue_timed(u, v); }*/
//#define SIZE 16384
#define SIZE 2048
//#define SIZE 32

QueueWrapper(const size_t &capacity) : queue( capacity ), done( false ){}
};
namespace Task {

//using EntryQueue_t = QueueWrapper<moodycamel::BlockingReaderWriterCircularBuffer<entry_t>>;
using XIAQueue_t = moodycamel::BlockingReaderWriterCircularBuffer<const XIA_base_t *>;
//using XIAQueue_t = moodycamel::BlockingReaderWriterCircularBuffer<XIA_base_t>;
using EntryQueue_t = moodycamel::BlockingReaderWriterCircularBuffer<Entry_t>;
using EventQueue_t = moodycamel::BlockingReaderWriterCircularBuffer<std::vector<Entry_t>>;
//using TEventQueue_t = moodycamel::BlockingReaderWriterCircularBuffer<std::pair<std::vector<Entry_t>, size_t>>;
using MCEventQueue_t = moodycamel::BlockingConcurrentQueue<std::vector<Entry_t>>;
using TEventQueue_t = moodycamel::BlockingConcurrentQueue<std::pair<std::vector<Entry_t>, size_t>>;
//using TEventQueue_t = moodycamel::BlockingReaderWriterCircularBuffer<Triggered_event>;
using XIAQueue_t = SPSCBlockingQueue<const XIA_base_t *, SIZE>;
using EntryQueue_t = SPSCBlockingQueue<Entry_t, SIZE>;
using EventQueue_t = SPSCBlockingQueue<std::vector<Entry_t>, SIZE>;
using MCEventQueue_t = SPSCBlockingQueue<std::vector<Entry_t>, SIZE>;
using TEventQueue_t = SPSCBlockingQueue<std::pair<std::vector<Entry_t>, int>, SIZE>;
using MTEventQueue_t = moodycamel::BlockingConcurrentQueue<std::pair<std::vector<Entry_t>, int>>;
}

#endif // QUEUE_H
78 changes: 78 additions & 0 deletions include/Tasks/SPMCQueue.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include <atomic>
#include <array>
#include <optional>
#include <thread>
#include <cstddef>

template<typename T, size_t Capacity>
class SPMCBlockingQueue
{
static_assert((Capacity & (Capacity - 1)) == 0,
"Capacity must be power of two");

private:

static constexpr size_t MASK = Capacity - 1;

alignas(64) std::array<T, Capacity> buffer;

alignas(64) std::atomic<size_t> read_index{0};
alignas(64) std::atomic<size_t> write_index{0};

bool is_finish = false;

public:

bool empty() const
{
return write_index.load(std::memory_order_acquire) ==
read_index.load(std::memory_order_acquire);
}

// Single producer (blocking when full)
void push(T value)
{
size_t w;

while (true)
{
w = write_index.load(std::memory_order_relaxed);
size_t r = read_index.load(std::memory_order_acquire);

if (w - r < Capacity)
break;

std::this_thread::yield(); // queue full
}

buffer[w & MASK] = std::move(value);

write_index.store(w + 1, std::memory_order_release);
}

// Multiple consumers
std::optional<T> pop()
{
while (true)
{
size_t r = read_index.load(std::memory_order_relaxed);
size_t w = write_index.load(std::memory_order_acquire);

if (r == w)
return std::nullopt;

if (read_index.compare_exchange_weak(
r,
r + 1,
std::memory_order_acq_rel,
std::memory_order_relaxed))
{
T value = std::move(buffer[r & MASK]);
return value;
}
}
}

void mark_as_finish(){ is_finish = true; }
bool is_not_finish() const { return !is_finish; }
};
Loading