似乎 CRITICAL_SECTION 性能在 Windows 8 及更高版本上变得更糟。(见下图)
测试非常简单:一些并发线程每个执行 300 万个锁来独占访问一个变量。您可以在问题底部找到 C++ 程序。我在 Windows Vista、Windows 7、Windows 8、Windows 10(x64、VMWare、Intel Core i7-2600 3.40GHz)上运行测试。
结果如下图所示。X 轴是并发线程数。Y 轴是以秒为单位的经过时间(越低越好)。
我们可以看到:
SRWLock 所有平台的性能大致相同CriticalSection 性能在 Windows 8 及更高版本上相对 SRWL 变差 问题是:谁能解释为什么 CRITICAL_SECTION 性能在 Win8 及更高版本上变得更糟?
一些注意事项:
std::mutexWindows Vista 的实现基于CRITICAL_SECTION,但 Win7 和更高版本std::mutex的实现基于 SWRL。它对 MSVS17 和 15 都是正确的(确保primitives.h在 MSVC++ 安装时搜索文件并查找stl_critical_section_vista和stl_critical_section_win7类)这解释了 Win Vista 和其他系统上 std::mutex 性能之间的差异。std::mutex是一个包装器,因此相对于 …搜索有关std算法性能的任何信息,我发现了关于std::max_element()与自写函数之间的性能差异的堆栈溢出问题。我已经用GCC 9.2.0测试了问题中的功能,没有发现性能差异,即my_max_element_orig()和my_max_element_changed()(从接受的答案中)显示出相同的性能。因此,这似乎只是GCC 4.8.2中的优化程序问题。对于GCC 9.2.0,我真正发现的是在使用指针和迭代器的情况下的显着差异-与原始指针相比,使用迭代器的情况要差2倍。如果使用,则迭代器和原始指针也有类似的区别std::max_element()。
让我们接受my_max_element_orig函数实现(见下文)并尝试运行测试。
template<typename _ForwardIterator>
_ForwardIterator my_max_element_orig(_ForwardIterator __first, _ForwardIterator __last)
{
if (__first == __last) return __first;
_ForwardIterator __result = __first;
while (++__first != __last)
if (*__result < *__first)
__result = __first;
return __result;
}
Run Code Online (Sandbox Code Playgroud)
以下用法示例
int maxValue = *my_max_element_orig(begin(vec), end(vec));
Run Code Online (Sandbox Code Playgroud)
比以下情况差(原始指针)
int maxValue = *my_max_element_orig(vec.data(), vec.data() + vec.size());
Run Code Online (Sandbox Code Playgroud)
可能有人说,原因是迭代器类的实现带来了一些开销。但是我发现原因是以下行的存在:
if (__first == __last) return __first;
Run Code Online (Sandbox Code Playgroud)
如果从函数中删除了上面的行,则迭代器显示的性能与原始指针相同。经过一些实验,我决定干预优化器的分支预测,并用以下内容替换该行:
#define unlikely(x) __builtin_expect((x),0)
...
if (unlikely(__first == …Run Code Online (Sandbox Code Playgroud) 我正在Linux中进行路径MTU发现的一些实验.据我所知,从RFC 1191中,如果路由器接收到一个非零DF位的数据包,并且该数据包无法在没有分段的情况下发送到下一个主机,那么路由器应丢弃数据包并将ICMP消息发送到初始发件人.
我在我的计算机上创建了几个VM,并按以下方式链接它们:
VM1 (192.168.100.2)
R1 (192.168.100.1,
192.168.150.1)
R2 (192.168.150.2,
192.168.200.1)
VM2 (192.168.200.2)
Run Code Online (Sandbox Code Playgroud)
Rx - 是安装了Linux的虚拟机,它们有两个带静态路由的网络接口.从V1 Ping V2并反之亦然.
traceroute from 192.168.100.2 to 192.168.200.2 (192.168.200.2)
1 192.168.100.1 (192.168.100.1) 0.437 ms 0.310 ms 0.312 ms
2 192.168.150.2 (192.168.150.2) 2.351 ms 2.156 ms 1.989 ms
3 192.168.200.2 (192.168.200.2) 43.649 ms 43.418 ms 43.244 ms
tracepath 192.168.200.2
1: ubuntu-VirtualBox.local 0.211ms pmtu 1500
1: 192.168.100.1 0.543ms
1: 192.168.100.1 0.546ms
2: 192.168.150.2 0.971ms
3: 192.168.150.2 1.143ms pmtu 750
3: 192.168.200.2 1.059ms reached
Run Code Online (Sandbox Code Playgroud)
段100.x和150.x具有MTU 1500.段200.x具有MTU 750.
我正在尝试发送启用了DF的UDP数据包.事实上,在数据包大小超过750的情况下,VM1根本不发送数据包(我收到了send()调用的EMSGSIZE错误). …
我的同事和我正在参加位于Accurev的一个大项目.我们已经创建了自己的工作区,后面有一些流(让我们称之为zzz-stream),许多其他参与者使用它们,而不仅仅是我们.
关键是我们希望在我们的工作空间之间交换我们的工作,进行一些更改,再次交换等等.在让其他人可以访问更改之前,换句话说,我们不希望传播我们的更改,直到它稳定并经过测试,但我们希望能够一起工作.
我的想法是创建支持zzz-stream的新流(yyy-stream),然后使用yyy-stream更改我们的工作空间.但不幸的是,我无权创建流.
我的第二个想法是使用工作区作为支持流,但它不起作用,因为Accurev不能使用ws作为支持流.
我们的问题有什么解决方案吗?
UPD:我最接受Brad的回答.然而,Accurev太重而且迟钝而无法有效使用.所以实际上我更喜欢使用Git来满足accurev工作区的内部需求.(外部见Accurev,内部git)
我有一个使用静态库的 C/C++ 项目。该图书馆是为“skylake”建筑而建的。该项目是一个数据处理模块,即它执行许多算术运算、内存复制、搜索、比较等。
CPU为至强金牌6130T,支持AVX512。我试图编译我的项目既-march=skylake和-march=skylake-avx512,然后用链接库。
在使用-march=skylake-avx512的情况下,与使用-march=skylake.
这怎么解释?可能是什么原因?
信息:
(C++)我有很多Entry类,并且得到了BaseProcessor接口,它包含了Entry处理逻辑.(见下面的代码)
Entry不提供运算符<().BaseProcessor提供指向较少(Entry,Entry)函数的指针,该函数特定于特定的BaseProcessor实现.
我可以使用函数指针来比较程序中的Entry实例.但是我需要为Entry类创建std :: set(或std :: map,或其他使用less()的东西).我试图使用std :: binary_function派生类将它传递给std :: set,但看起来我无法将函数指针值传递给模板.
我怎样才能做到这一点?用C++ 03可以吗?
谢谢.
struct Entry
{
// ...
private:
bool operator< (const Entry &) const; // Should be defined by BaseProcessor.
};
typedef bool (*LessFunc)(const Entry &, const Entry &);
class BaseProcessor
{
public:
// ...
virtual LessFunc getLessFunc () const = 0;
};
// ...
BaseProcessor *processor = getProcessor();
LessFunc lessfunc = processor->getLessFunc();
Entry e1;
Entry e2;
bool isLess = lessfunc(e1, e2); // OK
typedef std::set<Entry, ???> EntrySetImpl; …Run Code Online (Sandbox Code Playgroud)