Hello,
I am working on persisting SIMD data types found in the Vc library (which also comes with ROOT). Since ROOT doesn’t natively support I/O of Vc types (due to over-alignment), I have discussed with @pcanal and @Axel how to do this anyway. They proposed to use a persistent data type (such as std::vector) as an intermediary buffer to resp. store and load Vc types to and from.
I have successfully been able to do so, but only for SSE-compiled programs. When trying to do the same thing when compiling with AVX (i.e. adding the CXX_FLAG “-mavx”), I get strange I/O behavior. Sometimes I/O works, but sometimes it segfaults into the following:
#5 0x0000000000404c72 in ROOT::new_VcContainer(void*) ()
#6 0x00007f8019db7bc9 in TClass::New(TClass::ENewType, bool) const () from /home/ahmad/Desktop/root_v6.08.06_prebuilt/root/lib/libCore.so
#7 0x00007f80198161a5 in TKey::ReadObjectAny(TClass const*) () from /home/ahmad/Desktop/root_v6.08.06_prebuilt/root/lib/libRIO.so
#8 0x00007f801973d5a5 in TDirectoryFile::GetObjectChecked(char const*, TClass const*) () from /home/ahmad/Desktop/root_v6.08.06_prebuilt/root/lib/libRIO.so
#9 0x00000000004048bc in main ()
My version of ROOT is v6.08.06. The binaries were SSE-compiled. I also build ROOT with the “-mavx” flag enabled to see if it matters with which vectorization technique ROOT is built, but still the same problem.
Please find the reproducer below, consisting of vc_persistency.cc
, vc_persistency.h
, Makefile
and LinkDef.h
. When compiling please refer to your path to Vc in the variables CXXFLAGS
, LIBPATH
and LIBS
of the Makefile. Run ./avxRun
multiple times to see the strange I/O behavior I mentioned earlier (assuming your machine supports AVX).
// vc_persistency.cc
#include "vc_persistency.h"
int main(void) {
VcContainer *vcc = new VcContainer();
Vc::double_v v_set(42);
vcc->set_private(v_set);
vcc->PersistVc();
TFile *f = new TFile ("myfile.root", "RECREATE");
f->WriteObject(vcc, "VcObj");
f->Close();
VcContainer *vcc_r;
TFile *g = TFile::Open("myfile.root");
g->GetObject("VcObj", vcc_r);
g->Close();
vcc_r->LoadVc();
vcc_r->print_private();
remove("myfile.root");
}
// vc_persistency.h
#include <iostream>
#include <fstream>
#include <Rtypes.h>
#include <TFile.h>
#include <Vc/Vc>
class VcContainer {
public:
VcContainer(TRootIOCtor*) {} // ROOT I/O constructor
VcContainer() {}
void print_private() { std::cout << svc_d_ << std::endl; }
Vc::double_v& get_private() { return svc_d_; }
void set_private(Vc::double_v foo) {
for (int j = 0; j < static_cast<int>(Vc::double_v::Size); j++)
svc_d_[j] = foo[j];
}
virtual ~VcContainer() {}
void PersistVc() {
svc_d_pst_.clear();
for (size_t i = 0; i < Vc::double_v::Size; i++) {
svc_d_pst_.push_back(svc_d_[i]);
}
}
void LoadVc() {
for (size_t i = 0; i < Vc::double_v::Size; i++) {
svc_d_[i] = svc_d_pst_[i];
}
}
using pst_vector = std::vector<Vc::double_v::value_type>;
private:
int index_ = 0;
Vc::double_v svc_d_; //!
pst_vector svc_d_pst_;
ClassDef(VcContainer, 1);
};
ROOTCFLAGS = `root-config --cflags`
ROOTLIBS = `root-config --libs`
ROOTGLIBS = `root-config --glibs`
CXX = g++
CXXFLAGS = -I/opt/Vc/include -I$(ROOTSYS)/include -O -Wall -fPIC -Wno-reorder
FAVX = -mavx -fabi-version=6
FSSE = -msse -fabi-version=6
LD = g++
LDFLAGS = -g
SOFLAGS = -shared
LIBPATH = -L/opt/Vc/lib/
LIBS = -lVc
SSE = sseRun
AVX = avxRun
SOURCES = vc_persistency.cc
HEADERS = vc_persistency.h
LINKDEF = $(wildcard *LinkDef.h *Linkdef.h)
CXXFLAGS += $(ROOTCFLAGS)
GLIBS = $(ROOTGLIBS)
all: $(SSE) $(AVX)
clean:
@rm *.o *.pcm *.d *.so $(SSE) $(AVX) sseDict.cc avxDict.cc *.root 2>/dev/null || true
reset:
@rm *.root 2>/dev/null || true
# SSE Target
sseDict.cc: $(HEADERS) $(LINKDEF)
@rootcling -f $@ -c $(CXXFLAGS) -msse $(HEADERS) $(LINKDEF) 2>/dev/null || true
sseDict.o: sseDict.cc
@$(CXX) -c sseDict.cc $(CXXFLAGS) $(FSSE)
@echo "\033[95mBuilt sseDict.\033[0m"
$(SSE): $(SOURCES) sseDict.o
@$(CXX) $(SOURCES) $(LIBPATH) $(LIBS) -o $(SSE) sseDict.o $(CXXFLAGS) $(FSSE) $(GLIBS)
@echo "\033[95mBuilt executable $(SSE).\033[0m"
# AVX Target
avxDict.cc: $(HEADERS) $(LINKDEF)
@rootcling -f $@ -c $(CXXFLAGS) -mavx $(HEADERS) $(LINKDEF) 2>/dev/null || true
avxDict.o: avxDict.cc
@$(CXX) -c avxDict.cc $(CXXFLAGS) $(FAVX)
@echo "\033[95mBuilt avxDict.\033[0m"
$(AVX): $(SOURCES) avxDict.o
@$(CXX) $(SOURCES) $(LIBPATH) $(LIBS) -o $(AVX) avxDict.o $(CXXFLAGS) $(FAVX) $(GLIBS)
@echo "\033[95mBuilt executable $(AVX).\033[0m"
// LinkDef.h
#ifdef __ROOTCLING__
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ nestedclasses;
#pragma link C++ nestedtypedef;
#pragma link C++ class VcContainer+;
#endif
Any help on this matter would be greatly appreciated.
- Ahmad