1

假设我有一个二维数组和这个函数:

void addVec(std::vector<std::vector<short> >& arr, size_t idx){ 
   arr[idx].push_back(idx);
}

std::vector<std::vector<short> > arr(2);
boost::threads th1(addVec, boost::ref(arr), 0);
boost::threads th2(addVec, booost::ref(arr), 1);
th1.join();
th2.join();

现在我应该有 arr[0][0] = 0; 和 arr[1][0] = 1; 问题是这是否安全?在内部,线程应该将值添加到向量内存的不同部分,并且因为它是在大小为 2 的开头构造的,所以只有内部向量会调整大小,因此具有线程独占访问权限。

4

4 回答 4

4

这应该是安全的,因为每个线程都访问一个单独的向量。但是,如果您做了任何可能导致arr调整大小的事情,那么所有的赌注都没有了......

于 2012-11-06T11:01:05.300 回答
4

我建议您退后一步,考虑一下您的目标是什么,然后再继续前进。

首先,你为什么要并行化你的代码?我假设您希望您的程序运行得更快。这意味着

  1. 您应该从编写一个有效的顺序实现开始。
  2. 您应该分析和调整该实现。
  3. 如果(且仅当)您的程序对于您的目的来说仍然太慢,您应该在以下情况下并行化它:
    1. 程序的很大一部分可以并行化(查看Amdahl 定律)。
    2. 您的顺序实现很好地利用了缓存。即使对于顺序代码,缓存也很可能成为瓶颈,因此如果您的代码缓存效率不高,那么并行化它时它可能会变慢。

第 1 点和第 2 点可能是您应该花时间的地方。奇怪的是,高度调整的顺序实现足以满足您的需求,并且开发和维护它会便宜/更容易/更快。

如果你决定并行化你的代码,你应该看看OpenMP。线程可能是编写人类已知的并行程序的最糟糕的方法之一。您可能认为 OpenMP 的运行时系统对您来说太慢了,但同样,您应该退后一步想想原因。

如果您的算法需要大量锁和屏障,则可以通过使用更快的锁和屏障来获得较小的加速。如果你改进你的算法以使用更少的锁和障碍,你可以实现更大的加速。

于 2012-11-06T12:00:31.777 回答
2

这是安全的,尽管从设计的角度来看,给每个线程只提供其内部向量会更安全,因此未来发生不安全行为的可能性较小

于 2012-11-06T11:00:02.193 回答
2

是的,它在您的用例中是安全的,因为您不会修改共享数据。但是,我更愿意将引用传递std::vector<short>给每个线程以简化使用:

void addVec(std::vector<short> & arr)
{ 
   arr.push_back(some_data);
}

std::vector<std::vector<short> > arr(2);
boost::threads th1(addVec, boost::ref(arr[0]));
boost::threads th2(addVec, booost::ref(arr[1]));
th1.join();
th2.join();
于 2012-11-06T11:00:15.377 回答