小编flo*_*din的帖子

为什么我的日志库会导致性能测试运行得更快?

在过去的一年里,我一直在用C++开发一个记录库,并考虑到性能.为了评估性能,我开发了一组基准来比较我的代码与其他库,包括根本不执行日志记录的基本情况.

在我的上一个基准测试中,我测量了当日志记录处于活动状态时以及何时不处理时CPU密集型任务的总运行时间.然后我可以比较时间来确定我的库有多少开销.此条形图显示与我的非记录基础案例相比的差异.

绩效图表

正如您所看到的,我的库("鲁莽")增加了负面开销(除非所有4个CPU核心都忙).启用日志记录时,程序运行速度比禁用日程快约半秒.

我知道我应该尝试将其分解为一个更简单的案例,而不是询问一个4000行程序.但是有很多场所要去除什么,没有假设我会在试图隔离它时让问题消失.我可能会花一年时间做这件事.我希望Stack Overflow的集体专业知识能够使这个问题变得更加浅薄,或者对于那些比我有更多经验的人来说,这个原因是显而易见的.

关于我的图书馆和基准的一些事实:

  • 该库包含一个前端API,用于将日志参数推送到无锁队列(Boost.Lockless)和后端线程,后者执行字符串格式化并将日志条目写入磁盘.
  • 时间基于简单地调用std::chrono::steady_clock::now()程序的开头和结尾,并打印差异.
  • 基准测试运行在4核Intel CPU(i7-3770K)上.
  • 基准程序计算1024x1024 Mandelbrot分形并记录每个像素的统计数据,即它写入大约一百万个日志条目.
  • 单个工作线程案例的总运行时间约为35秒.因此速度提升约为1.5%.
  • 基准测试生成一个输出文件(这不是定时代码的一部分),其中包含生成的Mandelbrot分形.我已经验证打开和关闭日志记录时会产生相同的输出.
  • 基准测试运行100次(所有基准测试库,大约需要10个小时).条形图显示平均时间,误差条显示四分位数范围.
  • Mandelbrot计算的源代码
  • 基准的源代码.
  • 代码存储库和文档的根.

我的问题是,如何在启用日志记录库时解释明显的速度增加?

编辑:这是在尝试评论中给出的建议后解决的.我的日志对象是在基准测试的第24行创建的.显然,当LOG_INIT()触及日志对象时,它会触发页面错误,导致图像缓冲区的部分或全部页面映射到物理内存.我仍然不确定为什么这会使性能提高近半秒; 即使没有日志对象,mandelbrot_thread()函数中发生的第一件事就是写入图像缓冲区的底部,这应该具有类似的效果.但是,无论如何,在开始基准测试之前使用memset()清除缓冲区会使一切变得更加清晰.目前的基准是在这里

我试过的其他事情是:

  • 使用oprofile探查器运行它.我从来没有能够得到它的注册任何的锁定时间,甚至扩大就业,使其运行约10分钟后.几乎所有的时间都在Mandelbrot计算的内循环中.但也许我能够以不同的方式解释它们,因为我知道页面错误.我没想过要检查图像写入是否花费了不成比例的时间.
  • 卸下锁.这确实对性能产生了重大影响,但结果仍然很奇怪,无论如何我无法对任何多线程变体进行更改.
  • 比较生成的汇编代码.存在差异,但是日志记录构建显然做了更多的事情.没有什么能成为明显的表演杀手.

c++ performance multithreading

37
推荐指数
1
解决办法
1210
查看次数

在不获取LNK4006的情况下,将库与Visual C++中的依赖项链接起来

我有一组静态编译的库,库之间具有相当深的依赖性.例如,可执行文件X使用库A和B,A使用库C,B使用库C和D:

X -> A
     A -> C
X -> B
     B -> C
     B -> D
Run Code Online (Sandbox Code Playgroud)

当我将X与A和B链接时,如果C和D也没有添加到库列表中,我不想得到错误 - A和B在内部使用这些库的事实是X不应该需要的实现细节要了解.此外,当在依赖关系树中的任何位置添加新依赖项时,必须重新配置使用A或B的任何程序的项目文件.对于深度依赖关系树,所需库的列表可能变得非常长且难以维护.

所以,我正在使用A项目中Librarian部分的"Additional Dependencies"设置,添加C.lib.在B项目的同一部分,我添加了C.lib和D.lib.这样做的结果是图书馆员将C.lib捆绑成A.lib,将C.lib和D.lib捆绑成B.lib.

但是,当我链接X时,A.lib和B.lib都包含它们自己的C.lib副本.这导致了大量的警告

A.lib(c.obj):警告LNK4006"符号"(_symbol)已在B.lib(c.obj)中定义; 忽略第二个定义.

如何在不收到警告的情况下完成此操作?有没有办法简单地禁用警告,还是有更好的方法?

编辑:我看到不止一个答案表明,由于缺乏更好的替代方案,我只是禁用警告.嗯,这是问题的一部分:我甚至不知道如何禁用它!

warnings module visual-c++

21
推荐指数
2
解决办法
2万
查看次数

用于查找无与伦比的大括号/预处理程序指令的提示和工具

这是我最可怕的C/C++编译器错误之一:

file.cpp(3124):致命错误C1004:找到意外的文件结尾

file.cpp包含近百个头文件,后者又包含其他头文件.它超过3000线.代码应该模块化和结构化,源文件更小.我们应该重构它.作为程序员,总会有一个改进事物的愿望清单.

但是现在,代码很乱,截止日期即将来临.在所有这些行中的某个地方 - 很可能在其中一个包含的头文件中,而不是在源文件本身中 - 显然有一个无与伦比的支撑,无法匹配的#ifdef或类似.问题是,缺少点什么时,编译器真的不能告诉我哪里它丢失了.它只知道当它到达文件的末尾时,它不是正确的解析器状态.

您能否提供一些工具或其他提示/方法来帮助我找出错误原因?

c c++

14
推荐指数
2
解决办法
8458
查看次数

为什么Java中短整数除法的结果类型不是一个短整数?

考虑以下代码:

public class ShortDivision {
    public static void main(String[] args) {
        short i = 2;
        short j = 1;
        short k = i/j;
    }
}
Run Code Online (Sandbox Code Playgroud)

编译它会产生错误

ShortDivision.java:5: possible loss of precision
found   : int
required: short
        short k = i/j;
Run Code Online (Sandbox Code Playgroud)

因为表达式i/j的类型显然是int,因此必须强制转换为short.

为什么类型i/j不短?

java syntax

12
推荐指数
1
解决办法
7521
查看次数

如何设计具有多个不同成本的模拟退火的接受概率函数?

我正在使用模拟退火来解决NP完全资源调度问题.对于任务的每个候选顺序,我计算几个不同的成本(或能量值).一些例子(尽管具体细节可能与问题无关):

  • global_finish_time:计划跨越的总天数.
  • split_cost:由于其他任务中断而导致每个任务延迟的天数(这是为了阻止任务启动后中断).
  • deadline_cost:每个错过的截止日期过期的平方天数之和.

传统的接受概率函数看起来像这样(在Python中):

def acceptance_probability(old_cost, new_cost, temperature):
    if new_cost < old_cost:
        return 1.0
    else:
        return math.exp((old_cost - new_cost) / temperature)
Run Code Online (Sandbox Code Playgroud)

到目前为止,我已经将前两个成本合并为一个,只需添加它们,以便我可以将结果输入acceptance_probability.但我真正想要的是deadline_cost始终优先考虑global_finish_time,并global_finish_time优先考虑split_cost.

所以我对Stack Overflow的问题是:我如何设计一个考虑多个能量的接受概率函数,但总是认为第一个能量比第二个能量更重要,依此类推?换句话说,我想通过old_costnew_cost为一些费用元组和返回一个合理的值.

编辑:经过几天试验提出的解决方案后,我得出的结论是,对我来说唯一合适的方法是Mike Dunlavey的建议,尽管这会给成本组件带来许多其他困难.我实际上被迫将苹果与橙子进行比较.

所以,我付出了一些努力来"规范化"价值观.首先,deadline_cost是一个平方和,因此它呈指数增长,而其他组件线性增长.为了解决这个问题,我使用平方根来获得类似的增长率.其次,我开发了一个函数来计算成本的线性组合,但是根据到目前为止看到的最高成本组件自动调整系数.

例如,如果最高成本的元组是(A,B,C)并且输入成本向量是(x,y,z),则线性组合是BCx + Cy + z.这样,无论z有多高,它都不会比x值为1更重要.

这会在成本函数中产生"锯齿",因为会发现新的最大成本.例如,如果C上升,那么对于给定的(x,y,z)输入,BCx和Cy都将更高,因此成本之间的差异也将更高.较高的成本差异意味着接受概率将下降,就好像温度突然降低一个额外的步骤.在实践中,虽然这不是问题,因为最大成本在开始时仅更新几次,并且稍后不会更改.我相信这甚至可以在理论上证明收敛到正确的结果,因为我们知道成本会收敛到较低的值.

让我感到有些困惑的一件事是,当最高成本为1.0且更低时,例如0.5,会发生什么.使用(0.5,0.5,0.5)的最大向量,这将给出线性组合0.5*0.5*x + 0.5*y + z,即优先顺序突然反转.我想处理它的最好方法是使用最大向量来将所有值缩放到给定范围,这样系数总是可以相同(例如,100x + 10y + z).但我还没有尝试过.

optimization simulated-annealing np-complete

9
推荐指数
1
解决办法
6777
查看次数

将敏感应用数据作为电子邮件附件发送时,正确的权限处理是什么?

我无法为我希望以受控方式提供敏感数据的应用授予"反向权限".

我的应用程序是一个时间跟踪器,因为时间跟踪日志可以被视为个人信息,我已经创建了访问它的权限并为其分配了android.permission-group.PERSONAL_INFO权限组.

要从手机导出时间日志,我添加了将日志作为电子邮件附件发送的功能.附件由受我新添加的权限保护的内容提供商生成.我发送电子邮件的代码如下所示:

   String email = "someone@example.com";
   Uri uri = TimeLog.CSVAttachment.CONTENT_URI;
   Intent i = new Intent(Intent.ACTION_SEND, uri);
   i.setType("text/csv");
   i.putExtra(Intent.EXTRA_EMAIL, new String[]{email});
   i.putExtra(Intent.EXTRA_SUBJECT, "Time log");
   i.putExtra(Intent.EXTRA_TEXT, "Hello World!");
   i.putExtra(Intent.EXTRA_STREAM, uri);
   i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
   startActivity(i);
Run Code Online (Sandbox Code Playgroud)

在我的HTC手机上运行时,我会在Gmail和HTC邮件之间进行弹出式选择.选择Gmail,我在Gmail应用中遇到以下异常:

ERROR/AndroidRuntime(8169): Caused by: java.lang.SecurityException:
Permission Denial: reading com.mycompany.timelog.TimeLog uri
content://com.mycompany.timelog/csv_attachment from pid=8169,
uid=10035 requires com.mycompany.timelog.permission.READ_TIME_LOG
Run Code Online (Sandbox Code Playgroud)

我确实android:grantUriPermissions="true"设置了我的提供商,但这没有帮助.我有一个关于为什么会这样的理论.我曾预计FLAG_GRANT_READ_URI_PERMISSION会授予Gmail访问我的内容提供商的权利,但我认为真正发生的是此权限授予com.android.internal.app.ResolverActivity,因为Intent和Android创建了多个匹配项用于向用户显示选择的包装器活动.

所以,我尝试将其硬编码到我的应用程序中仅用于测试:

   grantUriPermission("com.google.android.gm", uri,
       Intent.FLAG_GRANT_READ_URI_PERMISSION);
Run Code Online (Sandbox Code Playgroud)

这允许Gmail正确显示电子邮件,我可以按"发送".不幸的是,在GMail关闭后,我在com.google.process.gapps中遇到了这个例外:

ERROR/AndroidRuntime(7617):java.lang.SecurityException:Permission Denial:从pid = 7617读取com.mycompany.timelog.TimeLog uri内容://com.mycompany.timelog/csv_attachment,uid = 10011要求 com.mycompany.timelog.permission.READ_TIME_LOG

请注意,这来自不同的PID和UID.这是因为对openAssetFile的实际调用是从属于不同包的某个同步提供程序组件(com.google.android.googleapps?)发生的.

虽然我有一些希望最终找到一种方法来向我的ACTION_SEND意图的最终接收者授予权限,但是对openAssetFile的调用是从一些完全不同且实际上不相关的包发生的事实让我感到困惑的是权限授予应该如何工作.

所以最终我的问题是,鉴于日志是敏感数据,我如何允许它作为附件通过电子邮件发送,同时尊重用户的隐私(例如,不使附件世界可读)?

android

6
推荐指数
1
解决办法
8095
查看次数

如何选择所选内容中的所有查找匹配项?

在Visual Studio Code中,我正在搜索正则表达式并启用了“在选择中查找”。现在,我要选择所有找到的匹配项。我的问题是,如果我从命令选项板中使用“选择所有出现的匹配项”,那么它将重复搜索整个文件并选择所有出现的情况。

如何将“选择所有出现的匹配项”限制为仅在原始选择项中的匹配项?

visual-studio-code

6
推荐指数
1
解决办法
1137
查看次数

对于很少使用统计数据的程序员,您可以建议哪些软件包?

作为一名程序员,我偶尔会发现需要分析大量数据,例如性能日志或内存使用数据,而且我总是很沮丧地花了多少时间做一些我希望更容易的事情.

作为将问题置于上下文中的示例,让我快速向您展示我今天收到的CSV文件中的示例(为简洁而严格过滤):

date,time,PS Eden Space used,PS Old Gen Used, PS Perm Gen Used
2011-06-28,00:00:03,45004472,184177208,94048296
2011-06-28,00:00:18,45292232,184177208,94048296
Run Code Online (Sandbox Code Playgroud)

我有大约100,000个像这样的数据点,我想在散点图中绘制不同的变量,以便查找相关性.通常,数据需要以某种方式进行处理以用于呈现目的(例如将纳秒转换为毫秒并舍入小数值),某些列可能需要添加或反转或组合(如日期/时间列).

这种工作的通常建议是R和我最近努力使用它,但经过几天的工作后,我的经验是我希望简单的大多数任务似乎需要很多步骤并且有特殊的例; 解决方案通常是非通用的(例如,将数据集添加到现有绘图中).它似乎是人们喜爱的那种语言之一,因为多年来积累的所有强大的库而不是核心语言的质量和实用性.

不要误解我的意思,我理解R对使用它的人的价值,只是因为我很少花时间在这种事情上,我认为我永远不会成为它的专家,而是非-expert每一项任务都变得过于繁琐.

Microsoft Excel在可用性方面非常出色,但它不足以处理大型数据集.此外,R和Excel都倾向于完全冻结(!)而不是等待或杀死进程,如果你不小心对太多数据做出错误的情节.

所以,堆栈溢出,你能推荐一些更适合我的东西吗?我不想放弃和开发自己的工具,我已经有足够的项目了.我喜欢互动的东西,可以使用硬件加速来绘制和/或剔除,以避免在渲染上花费太多时间.

statistics r

4
推荐指数
2
解决办法
1270
查看次数