mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
Merged eigen/eigen into default
This commit is contained in:
@@ -53,8 +53,10 @@ typedef __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if __cplusplus > 199711 || EIGEN_COMP_MSVC >= 1900
|
||||
|
||||
@@ -58,6 +58,18 @@
|
||||
#include "src/ThreadPool/SimpleThreadPool.h"
|
||||
#include "src/ThreadPool/NonBlockingThreadPool.h"
|
||||
|
||||
|
||||
// Use the more efficient NonBlockingThreadPool by default.
|
||||
namespace Eigen {
|
||||
#ifndef EIGEN_USE_SIMPLE_THREAD_POOL
|
||||
template <typename Env> using ThreadPoolTempl = NonBlockingThreadPoolTempl<Env>;
|
||||
typedef NonBlockingThreadPool ThreadPool;
|
||||
#else
|
||||
template <typename Env> using ThreadPoolTempl = SimpleThreadPoolTempl<Env>;
|
||||
typedef SimpleThreadPool ThreadPool;
|
||||
#endif
|
||||
} // namespace Eigen
|
||||
|
||||
#endif
|
||||
|
||||
#include <Eigen/src/Core/util/ReenableStupidWarnings.h>
|
||||
|
||||
@@ -418,7 +418,7 @@ class TensorContractionSubMapper {
|
||||
return m_base_mapper.template loadHalfPacket<Alignment>(i + m_vert_offset, m_horiz_offset);
|
||||
}
|
||||
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void storePacket(Index i, Packet p) const {
|
||||
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE void storePacket(Index i, const Packet& p) const {
|
||||
if (UseDirectOffsets) {
|
||||
m_base_mapper.storePacket(i, 0, p);
|
||||
}
|
||||
|
||||
@@ -88,11 +88,7 @@ static void initializeDeviceProp() {
|
||||
#if __cplusplus >= 201103L
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
#endif
|
||||
#if EIGEN_OS_WIN || EIGEN_OS_WIN64
|
||||
Sleep(1000);
|
||||
#else
|
||||
sleep(1);
|
||||
#endif
|
||||
EIGEN_SLEEP(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,17 +12,6 @@
|
||||
|
||||
namespace Eigen {
|
||||
|
||||
// Use the SimpleThreadPool by default. We'll switch to the new non blocking
|
||||
// thread pool later.
|
||||
#ifndef EIGEN_USE_SIMPLE_THREAD_POOL
|
||||
template <typename Env> using ThreadPoolTempl = NonBlockingThreadPoolTempl<Env>;
|
||||
typedef NonBlockingThreadPool ThreadPool;
|
||||
#else
|
||||
template <typename Env> using ThreadPoolTempl = SimpleThreadPoolTempl<Env>;
|
||||
typedef SimpleThreadPool ThreadPool;
|
||||
#endif
|
||||
|
||||
|
||||
// Barrier is an object that allows one or more threads to wait until
|
||||
// Notify has been called a specified number of times.
|
||||
class Barrier {
|
||||
|
||||
@@ -51,4 +51,12 @@
|
||||
#endif
|
||||
|
||||
|
||||
#if EIGEN_OS_WIN || EIGEN_OS_WIN64
|
||||
#define EIGEN_SLEEP(n) Sleep(n)
|
||||
#elif EIGEN_OS_GNULINUX
|
||||
#define EIGEN_SLEEP(n) usleep(n * 1000);
|
||||
#else
|
||||
#define EIGEN_SLEEP(n) sleep(std::max<unsigned>(1, n/1000))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,6 +28,7 @@ class NonBlockingThreadPoolTempl : public Eigen::ThreadPoolInterface {
|
||||
blocked_(0),
|
||||
spinning_(0),
|
||||
done_(false),
|
||||
cancelled_(false),
|
||||
ec_(waiters_) {
|
||||
waiters_.resize(num_threads);
|
||||
|
||||
@@ -61,10 +62,19 @@ class NonBlockingThreadPoolTempl : public Eigen::ThreadPoolInterface {
|
||||
|
||||
~NonBlockingThreadPoolTempl() {
|
||||
done_ = true;
|
||||
|
||||
// Now if all threads block without work, they will start exiting.
|
||||
// But note that threads can continue to work arbitrary long,
|
||||
// block, submit new work, unblock and otherwise live full life.
|
||||
ec_.Notify(true);
|
||||
if (!cancelled_) {
|
||||
ec_.Notify(true);
|
||||
} else {
|
||||
// Since we were cancelled, there might be entries in the queues.
|
||||
// Empty them to prevent their destructor from asserting.
|
||||
for (size_t i = 0; i < queues_.size(); i++) {
|
||||
queues_[i]->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
// Join threads explicitly to avoid destruction order issues.
|
||||
for (size_t i = 0; i < threads_.size(); i++) delete threads_[i];
|
||||
@@ -91,16 +101,25 @@ class NonBlockingThreadPoolTempl : public Eigen::ThreadPoolInterface {
|
||||
// completes overall computations, which in turn leads to destruction of
|
||||
// this. We expect that such scenario is prevented by program, that is,
|
||||
// this is kept alive while any threads can potentially be in Schedule.
|
||||
if (!t.f)
|
||||
if (!t.f) {
|
||||
ec_.Notify(false);
|
||||
else
|
||||
}
|
||||
else {
|
||||
env_.ExecuteTask(t); // Push failed, execute directly.
|
||||
}
|
||||
}
|
||||
|
||||
void Cancel() {
|
||||
cancelled_ = true;
|
||||
done_ = true;
|
||||
|
||||
// Let each thread know it's been cancelled.
|
||||
for (size_t i = 0; i < threads_.size(); i++) {
|
||||
threads_[i]->Cancel();
|
||||
threads_[i]->OnCancel();
|
||||
}
|
||||
|
||||
// Wake up the threads without work to let them exit on their own.
|
||||
ec_.Notify(true);
|
||||
}
|
||||
|
||||
int NumThreads() const final {
|
||||
@@ -135,6 +154,7 @@ class NonBlockingThreadPoolTempl : public Eigen::ThreadPoolInterface {
|
||||
std::atomic<unsigned> blocked_;
|
||||
std::atomic<bool> spinning_;
|
||||
std::atomic<bool> done_;
|
||||
std::atomic<bool> cancelled_;
|
||||
EventCount ec_;
|
||||
|
||||
// Main worker thread loop.
|
||||
@@ -145,7 +165,7 @@ class NonBlockingThreadPoolTempl : public Eigen::ThreadPoolInterface {
|
||||
pt->thread_id = thread_id;
|
||||
Queue* q = queues_[thread_id];
|
||||
EventCount::Waiter* waiter = &waiters_[thread_id];
|
||||
for (;;) {
|
||||
while (!cancelled_) {
|
||||
Task t = q->PopFront();
|
||||
if (!t.f) {
|
||||
t = Steal();
|
||||
@@ -158,7 +178,11 @@ class NonBlockingThreadPoolTempl : public Eigen::ThreadPoolInterface {
|
||||
// pool. Consider a time based limit instead.
|
||||
if (!spinning_ && !spinning_.exchange(true)) {
|
||||
for (int i = 0; i < 1000 && !t.f; i++) {
|
||||
t = Steal();
|
||||
if (!cancelled_.load(std::memory_order_relaxed)) {
|
||||
t = Steal();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
spinning_ = false;
|
||||
}
|
||||
@@ -207,8 +231,12 @@ class NonBlockingThreadPoolTempl : public Eigen::ThreadPoolInterface {
|
||||
int victim = NonEmptyQueueIndex();
|
||||
if (victim != -1) {
|
||||
ec_.CancelWait(waiter);
|
||||
*t = queues_[victim]->PopBack();
|
||||
return true;
|
||||
if (cancelled_) {
|
||||
return false;
|
||||
} else {
|
||||
*t = queues_[victim]->PopBack();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Number of blocked threads is used as termination condition.
|
||||
// If we are shutting down and all worker threads blocked without work,
|
||||
|
||||
@@ -71,7 +71,7 @@ class SimpleThreadPoolTempl : public ThreadPoolInterface {
|
||||
|
||||
void Cancel() {
|
||||
for (size_t i = 0; i < threads_.size(); i++) {
|
||||
threads_[i]->Cancel();
|
||||
threads_[i]->OnCancel();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ struct StlThreadEnvironment {
|
||||
public:
|
||||
EnvThread(std::function<void()> f) : thr_(std::move(f)) {}
|
||||
~EnvThread() { thr_.join(); }
|
||||
void Cancel() { EIGEN_THREAD_CANCEL(thr_); }
|
||||
// This function is called when the threadpool is cancelled.
|
||||
void OnCancel() { }
|
||||
|
||||
private:
|
||||
std::thread thr_;
|
||||
|
||||
@@ -19,8 +19,10 @@ class ThreadPoolInterface {
|
||||
// Submits a closure to be run by a thread in the pool.
|
||||
virtual void Schedule(std::function<void()> fn) = 0;
|
||||
|
||||
// Cancel all the threads in the pool.
|
||||
virtual void Cancel() = 0;
|
||||
// If implemented, stop processing the closures that have been enqueued.
|
||||
// Currently running closures may still be processed.
|
||||
// If not implemented, does nothing.
|
||||
virtual void Cancel() {}
|
||||
|
||||
// Returns the number of threads in the pool.
|
||||
virtual int NumThreads() const = 0;
|
||||
|
||||
Reference in New Issue
Block a user