我对这个std::async功能有点困惑.
规范说:正在执行的异步操作"好像在新的执行线程中"(C++11§30.6.8/ 11).
现在,这意味着什么?
在我的理解中,代码
std::future<double> fut = std::async(std::launch::async, pow2, num);
Run Code Online (Sandbox Code Playgroud)
应该pow2在新线程上启动函数并将值传递num给线程的值,然后在将来某个时候,当函数完成时,将结果放入fut(只要函数pow2具有类似的签名double pow2(double);).但规范说"似乎",这使得整个事情对我来说有点模糊.
问题是:
在这种情况下是否始终启动新线程?希望如此.我的意思是对我来说,参数std::launch::async是有意义的,我明确说明我确实想要创建一个新线程.
和代码
std::future<double> fut = std::async(std::launch::deferred, pow2, num);
Run Code Online (Sandbox Code Playgroud)
应该通过将函数调用延迟到我写的类似的点来使延迟评估成为可能.在这种情况下,参数,应该意味着我明确说明,我不想要一个新线程,我只是想确保在需要它的返回值时调用该函数.pow2var = fut.get();std::launch::deferred
我的假设是否正确?如果没有,请解释.
另外,我知道默认情况下该函数调用如下:
std::future<double> fut = std::async(std::launch::deferred | std::launch::async, pow2, num);
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我被告知是否将启动新线程取决于实现.那又是什么意思呢?
就我对资源管理的了解而言,在堆上分配一些东西(操作符new)应该总是比在堆栈上分配(自动存储)慢,因为堆栈是基于LIFO的结构,因此它需要最少的簿记,并且要分配的下一个地址的指针是微不足道的.
到现在为止还挺好.现在看下面的代码:
/* ...includes... */
using std::cout;
using std::cin;
using std::endl;
int bar() { return 42; }
int main()
{
auto s1 = std::chrono::steady_clock::now();
std::packaged_task<int()> pt1(bar);
auto e1 = std::chrono::steady_clock::now();
auto s2 = std::chrono::steady_clock::now();
auto sh_ptr1 = std::make_shared<std::packaged_task<int()> >(bar);
auto e2 = std::chrono::steady_clock::now();
auto first = std::chrono::duration_cast<std::chrono::nanoseconds>(e1-s1);
auto second = std::chrono::duration_cast<std::chrono::nanoseconds>(e2-s2);
cout << "Regular: " << first.count() << endl
<< "Make shared: " << second.count() << endl;
pt1();
(*sh_ptr1)();
cout << "As you can see, both are working …Run Code Online (Sandbox Code Playgroud) 我已经多次被告知,我应该使用参数std::async来解决火灾和遗忘类型的任务std::launch::async(所以它最好在新的执行线程上使用它).
在这些陈述的鼓励下,我想看看如何std::async比较:
std::thread我天真的异步实现看起来像这样:
template <typename F, typename... Args>
auto myAsync(F&& f, Args&&... args) -> std::future<decltype(f(args...))>
{
std::packaged_task<decltype(f(args...))()> task(std::bind(std::forward<F>(f), std::forward<Args>(args)...));
auto future = task.get_future();
std::thread thread(std::move(task));
thread.detach();
return future;
}
Run Code Online (Sandbox Code Playgroud)
没有看中这里,包函子f成std::packaged task与它的参数一起,启动它的一个新的std::thread被分离,并用返回std::future的任务.
现在代码测量执行时间std::chrono::high_resolution_clock:
int main(void)
{
constexpr unsigned short TIMES = 1000;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < TIMES; ++i)
{
someTask();
}
auto dur = …Run Code Online (Sandbox Code Playgroud) 我有一个简单的C ++应用程序,应该从名为POSIX的管道读取行:
#include<iostream>
#include<string>
#include<fstream>
int main() {
std::ifstream pipe;
pipe.open("in");
std::string line;
while (true) {
std::getline(pipe, line);
if (pipe.eof()) {
break;
}
std::cout << line << std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
脚步:
我创建了一个命名管道:mkfifo in。
我使用编译并运行C ++代码g++ -std=c++11 test.cpp && ./a.out。
我将数据输入in管道:
sleep infinity > in & # keep pipe open, avoid EOF
echo hey > in
echo cats > in
echo foo > in
kill %1 # this closes the pipe, C++ app stops on …Run Code Online (Sandbox Code Playgroud) 我知道,在某些情况下,您可以避免使用锁定互斥锁(std::mutex)std::atomic,从而提高性能.
你能说出这样的情况,并且最好显示一些关于如何做到这一点的示例代码(你如何使用std::atomic)?
此外,当我锁定互斥锁时,性能会下降,因为其他线程在互斥锁被锁定的一段时间内无法继续工作.这是互斥锁的唯一问题吗?我的意思是,锁定/解锁互斥锁是一项昂贵的操作,还是仅仅是我上面提到的?
我有一个N核处理器(在我的情况下为4).为什么在N个线程上N完全独立的函数调用大约快N倍(当然创建线程有开销,但是进一步阅读)?
查看以下代码:
namespace ch = std::chrono;
namespace mp = boost::multiprecision;
constexpr static unsigned long long int num = 3555;
// mp_factorial uses boost/multiprecision/cpp_int, so I get legit results
ch::steady_clock::time_point s1 = ch::steady_clock::now();
auto fu1 = std::async(std::launch::async, mp_factorial, num);
auto fu2 = std::async(std::launch::async, mp_factorial, num);
auto fu3 = std::async(std::launch::async, mp_factorial, num);
auto fu4 = std::async(std::launch::async, mp_factorial, num);
fu1.get(); fu2.get(); fu3.get(); fu4.get();
ch::steady_clock::time_point e1 = ch::steady_clock::now();
ch::steady_clock::time_point s2 = ch::steady_clock::now();
mp_factorial(num);
mp_factorial(num);
mp_factorial(num);
mp_factorial(num);
ch::steady_clock::time_point e2 = ch::steady_clock::now();
auto t1 = ch::duration_cast<ch::microseconds>(e1 …Run Code Online (Sandbox Code Playgroud) 我有一个子类threading.Thread.唯一的责任是将从UNIX命名管道读取的消息放入queue.Queue对象(以便其他线程可以在以后处理这些值).
示例代码:
class PipeReaderThread(Thread):
def __init__(self, results_queue, pipe_path):
Thread.__init__(self)
self._stop_event = Event()
self._results_queue = results_queue
self._pipe_path = pipe_path
def run(self):
while not self._stop_event.is_set():
with open(self._pipe_path, 'r') as pipe:
message = pipe.read()
self._results_queue.put(message, block=True)
def stop(self):
self._stop_event.set()
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我想使用一个threading.Event对象来停止循环,但由于命名管道上的open()或read()调用将阻塞(直到有人打开管道写入/写入然后关闭它),线程永远不会有机会停.
我不想对命名管道使用非阻塞模式,因为阻塞实际上是我想要的,我想等待某人打开并写入管道.
使用套接字我会尝试在套接字上设置超时标志,但我找不到任何方法为命名管道执行此操作.我还考虑过用冷血杀死线程而不给它机会优雅地停止,但这并不像我应该做的那样,我甚至不知道Python是否提供了这样做的方法.
我应该如何正确地停止这个线程,以便我可以join()在之后调用它?
我想创建一个用于实验目的的线程池(以及有趣的因素).它应该能够处理各种各样的任务(所以我可以在以后的项目中使用它).
在我的线程池类中,我将需要某种任务队列.由于标准库std::packaged_task从C++ 11标准开始提供,我的队列看起来像std::deque<std::packaged_task<?()> > task_queue,所以客户端可以std::packaged_task通过某种公共接口函数将s 推入队列(然后池中的一个线程将通知一个条件变量来执行它,等等.
我的问题与std::packaged_task<?()>deque中s 的模板参数有关.
函数签名?()应该能够处理任何类型/数量的参数,因为客户端可以执行以下操作:
std::packaged_task<int()> t(std::bind(factorial, 342));
thread_pool.add_task(t);
所以我不必处理参数的类型/数量.
但是回报价值应该是多少?(因此问号)
如果我将整个线程池类作为模板类,它的一个实例将只能处理具有特定签名的任务(如std::packaged_task<int()>).
我希望一个线程池对象能够处理任何类型的任务.
如果我使用std::packaged_task<void()>并且调用的函数返回一个整数,或者任何东西,那么这就是未定义的行为.
我有一个简单的shell脚本,其中包含以下内容:
#!/usr/bin/env bash
set -eu
set -o pipefail
Run Code Online (Sandbox Code Playgroud)
我还具有以下功能:
foo() {
printf "Foo working... "
echo "Failed!"
false # point of interest #1
true # point of interest #2
}
Run Code Online (Sandbox Code Playgroud)
执行foo()作为常规命令按预期工作:脚本退出时#1,由于返回码false是非零和我们使用set -e。
我的目标是将函数的输出捕获到foo()变量中,并仅在执行时出现错误时打印它foo()。这是我想出的:
printf "Doing something that could fail... "
if a="$(foo 2>&1)"; then
echo "Success!"
else
code=$?
echo "Error:"
printf "${a}"
exit $code
fi
Run Code Online (Sandbox Code Playgroud)
该脚本不会在处退出,#1并且会执行"Success!"该if语句的路径。注释掉trueat将#2导致执行语句的"Error:"路径 …
我知道,它std::shared_ptr使用引用计数,因此它具有复制和移动语义,另一方面std::unique_ptr(因此名称唯一)只有移动语义,因此尝试复制它是一个编译错误.
然而,对我而言,它并不十分清楚.我可以简单地使用std::shared_ptr了std::unique_ptr在大多数情况下,还是应该用std::unique_ptr尽可能因为它更有效,因为它没有照顾引用计数?
另外,我知道智能指针在处理时非常有用,例如异常安全,但它们通常会取代传统的T*指针吗?尽可能使用智能指针而不是传统T*指针是一种很好的编程习惯吗?