【发布时间】:2015-04-09 08:42:15
【问题描述】:
我想以多线程模式将对象放入std::vector。所以我决定比较两种方法:一种使用std::atomic,另一种使用std::mutex。我看到第二种方法比第一种方法快。为什么?
我使用 GCC 4.8.1,在我的机器(8 个线程)上,我看到第一个解决方案需要 391502 微秒,而第二个解决方案需要 175689 微秒。
#include <vector>
#include <omp.h>
#include <atomic>
#include <mutex>
#include <iostream>
#include <chrono>
int main(int argc, char* argv[]) {
const size_t size = 1000000;
std::vector<int> first_result(size);
std::vector<int> second_result(size);
std::atomic<bool> sync(false);
{
auto start_time = std::chrono::high_resolution_clock::now();
#pragma omp parallel for schedule(static, 1)
for (int counter = 0; counter < size; counter++) {
while(sync.exchange(true)) {
std::this_thread::yield();
};
first_result[counter] = counter;
sync.store(false) ;
}
auto end_time = std::chrono::high_resolution_clock::now();
std::cout << std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count() << std::endl;
}
{
auto start_time = std::chrono::high_resolution_clock::now();
std::mutex mutex;
#pragma omp parallel for schedule(static, 1)
for (int counter = 0; counter < size; counter++) {
std::unique_lock<std::mutex> lock(mutex);
second_result[counter] = counter;
}
auto end_time = std::chrono::high_resolution_clock::now();
std::cout << std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time).count() << std::endl;
}
return 0;
}
【问题讨论】:
-
1.请发布您的编译器、编译选项和测量结果。 2. 在测量后对结果数据做一些可观察的事情,否则足够好的优化器可以将代码删除为死代码。
-
在使用 Visual Studio 2013 的 32 位发布版本中,我得到 0、46800 和 64 位一致地给我 0、62400,所以看起来原子要么超级快,要么测试工具不是t 真的有效。如果您正在使用它,您还应该知道,在 Visual Studio 2013 及以下版本中,
high_resolution_clock与system_clock没有任何不同。 stackoverflow.com/q/16299029/920069 -
无论如何,这段代码都被严重破坏了。
memory_order_relaxed的原子操作不是同步操作。 -
我更新了我的代码。现在,当我使用四个线程时,第一个解决方案比第二个解决方案更快(25-30%)。但是如果我增加线程数(20-25%),第一个解决方案比第二个解决方案慢。
-
谁在乎。代码仍然被破坏。你认为你能得出什么结论?破码更快?破码更慢?这些有什么用?