小编Rom*_*098的帖子

为什么 CRITICAL_SECTION 性能在 Win8 上变差了

似乎 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 及更高版本上变得更糟?


一些注意事项:

  • 在真机上的结果几乎相同——CS 比 Win8 及更高版本上的 std::mutex、std::recursive_mutex 和 SRWL 差得多。但是我没有机会在具有相同 CPU 的不同操作系统上运行测试。
  • std::mutexWindows Vista 的实现基于CRITICAL_SECTION,但 Win7 和更高版本std::mutex的实现基于 SWRL。它对 MSVS17 和 15 都是正确的(确保primitives.h在 MSVC++ 安装时搜索文件并查找stl_critical_section_vistastl_critical_section_win7类)这解释了 Win Vista 和其他系统上 std::mutex 性能之间的差异。
  • 正如评论中所说,这std::mutex是一个包装器,因此相对于 …

c++ winapi critical-section c++11 stdmutex

5
推荐指数
1
解决办法
1467
查看次数

有没有一种方法可以优化性病算法?

搜索有关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)

c++ linux optimization gcc std

5
推荐指数
0
解决办法
107
查看次数

路径MTU发现 - ICMP响应在哪里?

我正在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错误). …

mtu icmp

4
推荐指数
1
解决办法
4039
查看次数

在accurev促进之前交换工作

我的同事和我正在参加位于Accurev的一个大项目.我们已经创建了自己的工作区,后面有一些流(让我们称之为zzz-stream),许多其他参与者使用它们,而不仅仅是我们.

关键是我们希望在我们的工作空间之间交换我们的工作,进行一些更改,再次交换等等.在让其他人可以访问更改之前,换句话说,我们不希望传播我们的更改,直到它稳定并经过测试,但我们希望能够一起工作.

我的想法是创建支持zzz-stream的新流(yyy-stream),然后使用yyy-stream更改我们的工作空间.但不幸的是,我无权创建流.

我的第二个想法是使用工作区作为支持流,但它不起作用,因为Accurev不能使用ws作为支持流.

我们的问题有什么解决方案吗?

UPD:我最接受Brad的回答.然而,Accurev太重而且迟钝而无法有效使用.所以实际上我更喜欢使用Git来满足accurev工作区的内部需求.(外部Accurev,内部git)

accurev

2
推荐指数
1
解决办法
255
查看次数

在编译时启用 AVX512 支持会显着降低性能

我有一个使用静态库的 C/C++ 项目。该图书馆是为“skylake”建筑而建的。该项目是一个数据处理模块,即它执行许多算术运算、内存复制、搜索、比较等。

CPU为至强金牌6130T,支持AVX512。我试图编译我的项目既-march=skylake-march=skylake-avx512,然后用链接库。

在使用-march=skylake-avx512的情况下,与使用-march=skylake.

这怎么解释?可能是什么原因?

信息:

  • Linux 3.10
  • 海湾合作委员会 9.2
  • 英特尔至强金牌 6130T

linux performance gcc x86-64 avx512

2
推荐指数
1
解决办法
1537
查看次数

使用指向函数的指针作为模板参数

(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)

c++ templates function-pointers

0
推荐指数
1
解决办法
741
查看次数