我在Visual Studio 11开发人员预览中遇到了一个错误,至少我认为这是一个错误并报告了它,但是我很感兴趣是否有人知道解决方法. 当我使用std::thread类创建多于一个线程时,它会导致应用程序崩溃.有时会引起异常,有时会导致访问违规,有时会起作用.复制错误的代码如下: #include #include #include #include int _tmain(int argc, _TCHAR* argv[]) { std::vector threads; for(int i = 0; i
以下是关于 multithreading 的编程技术问答
我正在尝试构建一个可以在多个内核上扩展的Tetris AI算法. 在我的测试中,事实证明,使用多个线程比使用单个线程慢. 经过一些研究,我发现我的线程大部分时间都在等待_Lockit _Lock(_LOCK_DEBUG).这是屏幕截图. 如您所见,锁应用于 local变量,无论如何都不需要任何锁! 我的问题是: 为什么stl锁定此向量? 如何使程序更快? (使用数组?) 更新 我通过在视觉工作室项目中设置这些命令行选项来消除锁定: /D "_HAS_ITERATOR_DEBUGGING=0" /D "_SECURE_SCL=0" 必须将其应用于解决方案文件中的所有项目,或者在运行时发生错误(迭代器等冲突). 我更改的第二件事是将std::vector更改为std::vector.我不知道std::vector太慢了. 解决方案 如果您在lock_debug中花费时间,则使用调试迭代器.
我希望访问基于STL的容器读取来自并行运行线程.无需使用任何实现的用户锁定.以下代码的基础是C ++ 11,并正确实现了标准. 一个> http://www.hpl.hpershp:/mm/threadsintro.html href =" http://www.open-std.org/jtc1/sc22/wg21/wg21/docs/papers/2012/n3376.pdf">当前草稿或 23.2.2容器数据竞赛[Container.Requirentess.Dataraces] 为了避免数据竞赛(17.6.5.9),实施应 考虑以下功能为const:开始,结束,rbegin, 渲染,正面,背面,数据,查找,lower_bound,upper_bound,quare_range, AT和,除了关联或无序的关联容器外, 操作员[]. 尽管有(17.6.5.9),需要实施 为了避免在包含对象的内容中的数据 除vector 以外的同一序列中的不同元素是 同时修改.
c ++ 17通过使用可选的执行电池参数(作为第一个参数),升级了69个STL算法以支持并行性.例如 std::sort(std::execution::par, begin(v), end(v)); 我怀疑C ++ 17标准故意说 如何实施多线程算法,使其由图书馆作者决定最好的是最好的(并允许他们改变他们的改变智力,以后).尽管如此,我还是渴望在高层次上了解并行STL算法的实施中考虑了哪些问题. 我脑海中的一些问题包括(但不限于!): 与机器上CPU和/或GPU内核数相关的最大线程数(由C ++应用程序)如何? 每种算法使用的线程数中有什么区别? (在每种情况下,每个算法都会始终使用相同数量的线程吗?) 在其他线程(在同一应用中)上其他并行STL调用是否有任何考虑? (例如,如果一个线程调用std :: for_each(par,...),它将根据std :: stort(par,...)是否在其他线程上运行(S)?也许有线程池吗?) 是否考虑到核心由于外部
我正在使用STD :: MAP来实现我的本地哈希表,该表将同时由多个线程访问. 我进行了一些研究,发现STD :: MAP不是线程安全的. 因此,我将使用MUTEX在地图上插入和删除操作. 我计划拥有单独的静音(ES),每个地图条目都可以独立修改. 我还需要在关键部分下找到操作吗? 发现操作会受到插入/删除操作的影响吗? 是否有比使用可以照顾一切的STD :: MAP更好的实现? 解决方案 您需要在关键部分中找到找到,但是您可能需要有两个不同的锁,一个用于写作,一个用于阅读.写锁定是独家的 这样的实现将与大多数STL实施一起使用,但这并不符合标准. std::map通常使用 red-black tree 读取元素时更改.如果该地图是使用 splay树相反,在查找过程中,该树只会改变,只有一个线程,只有一个线程可以一次阅读. 出于大多数目的,我建议使用两个锁. 其他解决方案 二进制树并不特别适合多线程,因为重新平衡可以在整个遍布遍布的修改中退化.此外,全局互斥
我有两个关于stl 的问题 1)为什么STL不是线程安全?是否有线程安全的结构? 2)如何使用GDB调试STL?在GDB中,如何打印向量? 解决方案 容器数据结构几乎总是需要同步(例如a 此螺纹 - 螺纹 - 圆形圆形圆形循环循环排队列车, . a vector包含一个连续的内存块.因此,一旦找到了该内存块的指针,就可以以与常规数组相同的方式显示.确切的细节取决于您使用的STL实现. 其他解决方案 标准C ++容器不是线程安全的,因为您实际上比仅仅是容器本身要更高的锁定锁定.换句话说,您可能希望两个或多个操作一起安全. 例如,如果您运行多个线程: v.push_back(0); v.push_back(1); you 不会获得交替的0和1的很好的向量,它们可能会被混乱.您需要锁定两个命令才能获得想要的东西. 其他解决方案 STL不是线程安全,因为很多人不需要线程安全,并且因为这将线程上下文引入了类,而这些上下文否则无需了解线程概念.
我很难理解函数对象作为C ++ STL中的线程例程的正确用法.从我的理解来看,函子的好处之一是对象实例可以维护状态.有时我希望一个或多个线程运行一些例程并计算一些结果.然后,我加入线程后,我从对象中查询这些结果.我正在尝试使用C ++ STL线程进行操作,并遇到一些问题.问题似乎是由于C ++ STL线程制作了我的对象的副本,因此我不确定在加入线程时如何检查结果.这是代码的片段: #include #include using namespace std; class Worker { public: Worker() : _value(0) { } void operator()(unsigned int value); unsigned int get_value() {return this->_value;} private: unsigned int _value; };
如此,以及一般的互联网,如何使OpenMP易于使用的#pragma指令与C ++同样易于使用的STL容器合作存在很多混乱和沮丧. 每个人都在谈论STL vector的工作范围,但是非随机访问/双向容器,例如map,list,set等? 我遇到了这个问题,并设计了一个非常简单,明显的解决方法.我在这里以stl map介绍它,但显然是可以推广的. 串行版本: for (std::map::iterator it = my_map.begin(); it != my_map.end(); ++it) { /* do work with it */ } 我提出的解决方案是将OpenMP与STL map使用: //make an array of iterators. int loop_length = my_map.size(); std::map::ite
std :: random_shuffle threadsafe?我认为不是因为普通兰特()不是线程安全.如果是这样,我将如何将rand_r与Random_shuffle一起使用,以便我可以给每个线程一个唯一的种子.我已经看到使用随机_shuffle的自定义随机生成器的示例,但我仍然不清楚. 谢谢. 解决方案 要在std::random_shuffle上使用rand_r,您需要编写(相当微不足道的)包装器.您传递给random_shuffle的随机数生成器需要接受指定要生成的数字范围的参数,rand_r 您的包装器看起来像这样: class rand_x { unsigned int seed; public: rand_x(int init) : seed(init) {} int operator()(int limit) { int divisor = RAND_MAX/(limit+1); in
我正在尝试使用C ++ 11的std ::线程.如果可以在执行其功能成员之一的类中,我找不到任何地方的std ::线程.考虑下面的示例... 在我的尝试(下图)中,该函数是运行(). i用gcc -4.4与-std = c ++ 0x flag. #ifndef RUNNABLE_H #define RUNNABLE_H #include class Runnable { public: Runnable() : m_stop(false) {m_thread = std::thread(Runnable::run,this); } virtual ~Runnable() { stop(); } void stop() { m_stop = false; m_thread.join(); } protected: virtual void run() = 0;
c ++'s std::mutex没有移动构造函数.有一个有充分的理由.基本上,移动构造函数本身通常不是线程安全的,而静音的整个点是多个线程将尝试同时访问它. 不幸的是,静音不能直接放置在容器中.容器需要能够安全地移动其内容的能力,而您无法使用静音. 简单的出路是只用一个单独的静音保护整个容器.但是,假设我想要比这更细粒度的控制吗?如果我通过容器(例如:std::map)实现数据库,那么希望能够锁定单个记录,而不仅仅是整个数据库. . 下一步想到的是使用std::unique_ptr来解决问题.那会编译,但并没有真正改变基本问题,是吗?移动问题的情况是thread1在使用该容器条目的中间,thread1在thread1上进行了引起输入移动的容器更改.在这种情况下,thread2最终可以轻松地拿着破坏的条目或智能指针.似乎无论如何,您最终必须在做任何事情之前都必须用互惠件锁定整个容器. 似乎应该有一个已知的习语来做这类事情. 解决方案 Mutex不需要移动:
在用C ++ 11编写的分布式作业系统中,我已经实现了一个围栏(即,在工作线程池外的线程可能会要求阻止直到当前计划的所有计划完成): struct fence { std::atomic counter; std::mutex resume_mutex; std::condition_variable resume; fence(size_t num_threads) : counter(num_threads) {} }; 实现围栏的代码如下: void task_pool::fence_impl(void *arg) { auto f = (fence *)arg; if (--f->counter == 0) // (1)
tbb::scalable_allocator在英特尔螺纹构建块中实际上在引擎盖下做什么? 当然可以有效.我刚刚使用它可以通过将单个std::vector更改为std::vector >来利用应用程序的执行时间(并看到CPU利用率从〜200%增加到350%).另一方面,在另一个应用程序中,我看到它已经使已经大量的内存消耗加倍,并将其发送到交换城市. 英特尔自己的文档并不能放弃很多东西(例如,在此常见问题).谁能告诉我在我自己去挖掘它的代码之前使用什么技巧? 更新:首次使用TBB 3.0,然后看到我从可伸缩_Allocator中获得的最佳加速.将单个vector更改为vector >将某物的运行时间从85s降低到35s(Debian Lenny,Core2,带有测试的TBB 3.0). 解决方案 分配器上有一张好论文:在英特尔线程构建块
我有一个std ::映射,我用来将其映射为人类可读字符串.当我的程序启动之前启动任何其他线程之前,该地图是初始化的一次,此后再也不会对其进行修改.目前,我将每个线程的每个线程均已自己的(相当大)地图副本提供,但这显然是对内存的效率低下,并且会减慢程序启动.因此,我正在考虑将每个线程指向地图指针,但这引发了线程安全问题. 如果我要做的就是使用以下代码从地图上阅读: std::string name; //here N is the field id for which I want the human readable name unsigned field_id = N; std::map::const_iterator map_it; // fields_p is a const std::map* to the map concerned. // multiple threads
我有一个std :: list 容器和这些线程: 一个无限期添加元素的作者线程. 一个读者/作者线程可在可用时读取和删除元素. 几个读取器线程访问容器的大小(使用size()方法) 有一个普通的静音,可以保护前两个线程中对列表的访问.我的问题是,尺寸的读取器线程也需要获取此互斥品吗?我应该使用读/写utex吗? 我使用Visual C ++6. 在Windows环境中 更新:看起来答案尚不清楚.总结主要的疑问:即使我只调用size()(返回一个简单的变量),我仍然需要保护尺寸读取器线程,而我不需要确切的值(即我可以假设一个+/- 1变体)?种族条件如何使我的大小()呼叫返回无效的值(即一个与好的值完全无关)? 答案:通常,必须保护读者线程以避免种族条件.尽管如此,我认为,上面在更新中提到的一些问题尚未回答. 预先感谢! 谢谢大家的回答! 是的 读者/作家穆特斯应该足够了.但是严格来说,这是一个特定于暗示的问题.即使在您的代码中仅读取
假设我有一个n元素的向量,但是该向量的最多n要素具有有意义的数据.一个更新程序线程更新nth或n+1st元素(然后设置n = n+1),还检查n是否太近n并在必要时调用vector :: ressize(n+m).更新后,线程调用多个子线程以阅读最多nth数据并进行一些计算. 可以保证,儿童线程永远不会更改或删除数据(实际上没有删除任何数据),并且在完成更新后,更新者将调用儿童. 到目前为止没有问题,但是我想询问是否在将矢量重新定位到更大的内存块期间是否会出现问题,如果以前的更新中剩下一些孩子的工作线程. 还是在这种多线程中使用矢量不是线程安全的,因为它不是线程的? 编辑: 由于只有在更新程序调用vector ::大小(n+m,0)时进行插入,我是否有可能解决我的问题的解决方案?由于STL向量的出色表现,我不愿意用可锁的向量代替它,或者在这种情况下,是否有任何表演者,已知和无锁的向量? 解决方案 我想询问在将向量重新定位到更大的内存块时是否会出现问题,