我正在构建一个模拟器来测试一个非常简单的机器人的学生代码。我需要定期在不同的线程上运行两个功能(更新机器人传感器和机器人位置)。我目前的实现是高效率的处理器,因为它有一个线程专门用于简单地递增数字以跟踪代码中的位置。我最近的理论是,我可以使用睡眠来给出更新传感器值和机器人位置之间的时间延迟。我的第一个问题是:这是否有效?第二:有没有办法做简单的事情,但测量时钟周期而不是秒?使用线程定时调用函数
回答
通过等待类似互斥体的对象使线程进入睡眠通常是有效的。一种常见的模式包括等待一个超时的互斥体。达到超时时间后,时间间隔结束。当互斥体被释放时,它是线程终止的信号。
伪代码:
void threadMethod() {
for(;;) {
bool signalled = this->mutex.wait(1000);
if(signalled) {
break; // Signalled, owners wants us to terminate
}
// Timeout, meaning our wait time is up
doPeriodicAction();
}
}
void start() {
this->mutex.enter();
this->thread.start(threadMethod);
}
void stop() {
this->mutex.leave();
this->thread.join();
}
在Windows系统中,超时通常以毫秒为单位指定和精确到大约16内毫秒(timeBeginPeriod()
可能能够改善这一点)。我不知道CPU周期触发的同步原语。在委派给OS线程调度器之前,有一些称为“关键部分”的轻量级互斥体,可让CPU旋转几千个周期。在这段时间内,它们相当准确。
在Linux系统上,准确度可能会高一些(高频定时器或无滴答内核),除了互斥锁之外,还有类似于Windows临界区的“futexes”(快速互斥锁)。
我不知道我抓住你想要达到什么样的,但如果你想测试学生的代码,你可能想要使用虚拟时钟和控制自己时间的流逝。例如,通过调用学生必须提供的processInputs()
和decideMovements()
方法。每次通话后,1个时隙到了。
是的,你的理论是正确的。你可以使用睡眠来在线程执行一个函数之间放一些延迟。效率取决于您可以选择多大的延迟以获得期望的结果。 你必须解释你的实施细节。例如,我们不知道两个线程是否有依赖关系(在这种情况下,您必须注意可能会导致一些周期的同步)。
你可以使用'sleep()',是的。但是在大多数情况下,这可能是一个非常糟糕的主意(你可能会忙于等待)。更合适的方法是使用定时信号/条件变量。 – 2014-10-27 18:22:24
这个C++ 11代码使用std::chrono::high_resolution_clock
来测量亚秒的时间,而std::thread
运行三个线程。 std::this_thread::sleep_for()
函数用于在指定的时间内休眠。
#include <iostream>
#include <thread>
#include <vector>
#include <chrono>
void seconds()
{
using namespace std::chrono;
high_resolution_clock::time_point t1, t2;
for (unsigned i=0; i<10; ++i) {
std::cout << i << "\n";
t1 = high_resolution_clock::now();
std::this_thread::sleep_for(std::chrono::seconds(1));
t2 = high_resolution_clock::now();
duration<double> elapsed = duration_cast<duration<double> >(t2-t1);
std::cout << "\t(" << elapsed.count() << " seconds)\n";
}
}
int main()
{
std::vector<std::thread> t;
t.push_back(std::thread{[](){
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "awoke after 3\n"; }});
t.push_back(std::thread{[](){
std::this_thread::sleep_for(std::chrono::seconds(7));
std::cout << "awoke after 7\n"; }});
t.push_back(std::thread{seconds});
for (auto &thr : t)
thr.join();
}
很难知道这是否符合您的需求,因为这个问题中缺少很多细节。在Linux下,编译:我的机器上
g++ -Wall -Wextra -pedantic -std=c++11 timers.cpp -o timers -lpthread
输出:
0
(1.00014 seconds)
1
(1.00014 seconds)
2
awoke after 3
(1.00009 seconds)
3
(1.00015 seconds)
4
(1.00011 seconds)
5
(1.00013 seconds)
6
awoke after 7
(1.0001 seconds)
7
(1.00015 seconds)
8
(1.00014 seconds)
9
(1.00013 seconds)
其他C++ 11个的标准功能,可能会感兴趣的包括timed_mutex和promise/future。
以下是一种方法。我使用C++ 11,线程,原子和高精度时钟。调度器将回调一个函数,该函数需要dt秒,这是自上次调用以来已过去的时间。如果回调函数返回false,则可以通过调用stop()方法来停止循环。
调度代码
#include <thread>
#include <chrono>
#include <functional>
#include <atomic>
#include <system_error>
class ScheduledExecutor {
public:
ScheduledExecutor()
{}
ScheduledExecutor(const std::function<bool(double)>& callback, double period)
{
initialize(callback, period);
}
void initialize(const std::function<bool(double)>& callback, double period)
{
callback_ = callback;
period_ = period;
keep_running_ = false;
}
void start()
{
keep_running_ = true;
sleep_time_sum_ = 0;
period_count_ = 0;
th_ = std::thread(&ScheduledExecutor::executorLoop, this);
}
void stop()
{
keep_running_ = false;
try {
th_.join();
}
catch(const std::system_error& /* e */)
{ }
}
double getSleepTimeAvg()
{
//TODO: make this function thread safe by using atomic types
//right now this is not implemented for performance and that
//return of this function is purely informational/debugging purposes
return sleep_time_sum_/period_count_;
}
unsigned long getPeriodCount()
{
return period_count_;
}
private:
typedef std::chrono::high_resolution_clock clock;
template <typename T>
using duration = std::chrono::duration<T>;
void executorLoop()
{
clock::time_point call_end = clock::now();
while (keep_running_) {
clock::time_point call_start = clock::now();
duration<double> since_last_call = call_start - call_end;
if (period_count_ > 0 && !callback_(since_last_call.count()))
break;
call_end = clock::now();
duration<double> call_duration = call_end - call_start;
double sleep_for = period_ - call_duration.count();
sleep_time_sum_ += sleep_for;
++period_count_;
if (sleep_for > MinSleepTime)
std::this_thread::sleep_for(std::chrono::duration<double>(sleep_for));
}
}
private:
double period_;
std::thread th_;
std::function<bool(double)> callback_;
std::atomic_bool keep_running_;
static constexpr double MinSleepTime = 1E-9;
double sleep_time_sum_;
unsigned long period_count_;
};
示例用法
bool worldUpdator(World& w, double dt)
{
w.update(dt);
return true;
}
void main() {
//create world for your simulator
World w(...);
//start scheduler loop for every 2ms calls
ScheduledExecutor exec;
exec.initialize(
std::bind(worldUpdator, std::ref(w), std::placeholders::_1),
2E-3);
exec.start();
//main thread just checks on the results every now and then
while (true) {
if (exec.getPeriodCount() % 10000 == 0) {
std::cout << exec.getSleepTimeAvg() << std::endl;
}
}
}
- 1. Boost线程不调用线程函数
- 2. Qt线程调用函数
- 3. 从线程调用函数
- 4. 多线程函数调用
- 5. 多线程调用函数定义在C从TCL线程
- 6. 调用成员函数作为线程函数使用boost
- 7. 多线程 - 每个线程在特定时间后调用函数
- 8. 使用函数指针从线程调用回调
- 9. C++定时器,线程,定期调用
- 10. 使用预定义函数时回调
- 11. 使用Haskell回调函数调用多线程C FFI时的计划错误
- 12. 从工作线程调用主线程回调函数
- 13. iOS:在回调函数中调用setNeedDisplay时的线程问题
- 14. 使用多线程中的输入参数调用函数
- 15. 使用C函数时调用函数或程序fopen
- 16. (python)使用线程调用时的不同行为。定时器
- 17. 如何在成员函数线程中调用回调函数?
- 18. 在新线程powershell中调用函数
- 19. 从主线程函数调用方法
- 20. 线程调用成员函数
- 21. 线程中的iOS调用soap函数
- 22. 参考C++多线程函数调用
- 23. 线程的run()函数调用
- 24. 线程不会调用函数(Python)
- 25. 稍后调用线程函数
- 26. 在OpenMP fortran线程中调用函数
- 27. 与Java交叉线程函数调用
- 28. Python单线程调用函数列表
- 29. 线程中断与JNI函数调用
- 30. pthread_exit来自线程调用的函数
你能详细解释一下你希望做什么吗?为什么传感器和位置有不同的线程?这两个线程是否以任何方式相互依赖?除非测试代码正在做一些非常繁重的工作,否则我怀疑你需要认真关注优化测试代码的效率。 – 2014-10-27 18:03:32