From 07a9105a5214c3959b1597a462baec41f5826e62 Mon Sep 17 00:00:00 2001
From: Berenger Bramas <Berenger.Bramas@inria.fr>
Date: Thu, 28 Jan 2016 11:45:05 +0100
Subject: [PATCH] add cuda help classes (mem object and timer)

---
 Src/GroupTree/Cuda/FCudaData.hpp |  77 +++++++++++++++++++++++
 Src/GroupTree/Cuda/FCudaTic.hpp  | 102 +++++++++++++++++++++++++++++++
 2 files changed, 179 insertions(+)
 create mode 100644 Src/GroupTree/Cuda/FCudaData.hpp
 create mode 100644 Src/GroupTree/Cuda/FCudaTic.hpp

diff --git a/Src/GroupTree/Cuda/FCudaData.hpp b/Src/GroupTree/Cuda/FCudaData.hpp
new file mode 100644
index 000000000..49c501152
--- /dev/null
+++ b/Src/GroupTree/Cuda/FCudaData.hpp
@@ -0,0 +1,77 @@
+#ifndef FCUDADATA_HPP
+#define FCUDADATA_HPP
+
+#include "FCudaGlobal.hpp"
+
+template <class ObjectClass>
+class FCudaData{
+protected:
+    ObjectClass* cudaPtr;
+    FSize nbElements;
+
+    void allocAndCopy(const ObjectClass* inCpuPtr, const FSize inNbElements){
+        FCudaCheck( cudaMalloc(&cudaPtr,inNbElements*sizeof(ObjectClass)) );
+        FCudaCheck( cudaMemcpy( cudaPtr, inCpuPtr, inNbElements*sizeof(ObjectClass),
+                    cudaMemcpyHostToDevice ) );
+    }
+
+    void dealloc(){
+        FCudaCheck(cudaFree(cudaPtr));
+        cudaPtr = nullptr;
+        nbElements = 0;
+    }
+public:
+    FCudaData(const FCudaData&) = delete;
+    FCudaData& operator=(const FCudaData&) = delete;
+
+    FCudaData(const ObjectClass* inCpuPtr, const FSize inNbElements)
+        : cudaPtr(nullptr), nbElements(0){
+        allocAndCopy(inCpuPtr, inNbElements);
+    }
+
+
+    FCudaData(FCudaData&& other)
+        : cudaPtr(nullptr), nbElements(0){
+        this->cudaPtr = other->cudaPtr;
+        this->nbElements = other->nbElements;
+        other->cudaPtr = nullptr;
+        other->nbElements = 0;
+    }
+
+    FCudaData& operator=(FCudaData&& other){
+        dealloc();
+        this->cudaPtr = other->cudaPtr;
+        this->nbElements = other->nbElements;
+        other->cudaPtr = nullptr;
+        other->nbElements = 0;
+    }
+
+
+    ~FCudaData(){
+        dealloc();
+    }
+
+    void release(){
+        dealloc();
+    }
+
+    ObjectClass* get() {
+        return cudaPtr;
+    }
+
+    const ObjectClass* get() const {
+        return cudaPtr;
+    }
+
+    FSize getSize() const {
+        return nbElements;
+    }
+
+    void copyToHost(ObjectClass* inCpuPtr){
+        FCudaCheck( cudaMemcpy( inCpuPtr, cudaPtr, nbElements*sizeof(ObjectClass),
+                    cudaMemcpyDeviceToHost ) );
+    }
+};
+
+#endif // FCUDADATA_HPP
+
diff --git a/Src/GroupTree/Cuda/FCudaTic.hpp b/Src/GroupTree/Cuda/FCudaTic.hpp
new file mode 100644
index 000000000..9d75a0e06
--- /dev/null
+++ b/Src/GroupTree/Cuda/FCudaTic.hpp
@@ -0,0 +1,102 @@
+#ifndef FCUDATIC_HPP
+#define FCUDATIC_HPP
+
+#include "FCudaGlobal.hpp"
+
+
+/**
+ * \brief Time counter class.
+ * \author Berenger Bramas (berenger.bramas@inria.fr)
+ *
+ * This time counter can be (re)started using tic() and stopped using tac().
+ *
+ *  - use elapsed() to get the last time interval;
+ *  - use cumulated() to get the total running time;
+ *  - use reset() to stop and reset the counter.
+ *
+ * \code
+ * FCudaTic timer;
+ * timer.tic();
+ * //...(1)
+ * timer.tac();
+ * timer.elapsed();  // time of (1) in s
+ * timer.tic();
+ * //...(2)
+ * timer.tac();
+ * timer.elapsed();  // time of (2) in s
+ * timer.cumulated() // time of (1) and (2) in s
+ * timer.reset()     // reset the object
+ * \endcode
+ *
+ */
+class FCudaTic {
+private:
+
+    cudaStream_t stream;
+    cudaEvent_t start    = 0;    ///< start time (tic)
+    cudaEvent_t end      = 0;    ///< stop time (tac)
+    double cumulate = 0;    ///< the cumulate time
+
+public:
+    /// Constructor
+    explicit FCudaTic(const cudaStream_t inStream = 0)
+        : stream(inStream){
+        FCudaCheck(cudaEventCreate(&start));
+        FCudaCheck(cudaEventCreate(&end));
+        tic();
+    }
+
+    ~FCudaTic(){
+        FCudaCheck( cudaEventDestroy( start ) );
+        FCudaCheck( cudaEventDestroy( end ) );
+    }
+
+    /// Copy constructor
+    FCudaTic(const FCudaTic& other) = delete;
+    /// Copy operator
+    FCudaTic& operator=(const FCudaTic& other) = delete;
+
+
+    /// Resets the timer
+    /**\warning Use tic() to restart the timer. */
+    void reset() {
+        cumulate = 0;
+    }
+
+    /// Start measuring time.
+    void tic(){
+        FCudaCheck(cudaEventRecord( start, stream ));
+    }
+
+    /// Stop measuring time and add to cumulated time.
+    void tac(){
+        FCudaCheck(cudaEventRecord( end, stream ));
+        FCudaCheck(cudaEventSynchronize( end ));
+        cumulate += elapsed();
+    }
+
+    /// Elapsed time between the last tic() and tac() (in seconds).
+    /** \return the time elapsed between tic() & tac() in second. */
+    double elapsed() const{
+        float elapsedTime;
+        FCudaCheck( cudaEventElapsedTime( &elapsedTime, start, end ) ); // in ms
+        return elapsedTime/1000.0;
+    }
+
+    /// Cumulated tic() - tac() time spans
+    /** \return the time elapsed between ALL tic() & tac() in second. */
+    double cumulated() const{
+        return cumulate;
+    }
+
+    /// Combination of tic() and elapsed().
+    /** \return the time elapsed between tic() & tac() in second. */
+    double tacAndElapsed() {
+        tac();
+        return elapsed();
+    }
+};
+
+
+#endif // FCUDATIC_HPP
+
-- 
GitLab