Questions tagged «performance»

对于与代码的度量或改进以及应用程序效率有关的问题。

1
高效的字符串截断算法,顺序删除相等的前缀和后缀
每次测试的时间限制:5秒 每次测试的内存限制:512 MB 系统会为您提供一串s长度n(n≤5000)的字符串。您可以选择该字符串的任何适当前缀(也就是其后缀),然后删除所选的前缀或相应的后缀。然后,您可以对结果字符串应用类似的操作,依此类推。应用最佳操作顺序后,最终字符串的最小长度是多少? 输入 每个测试的第一行包含一个s由小英文字母组成的字符串。 输出 输出单个整数-最终字符串的最小长度,可以在应用此类操作的最佳顺序后实现。 例子 +-------+--------+----------------------------------+ | Input | Output | Explanation | +-------+--------+----------------------------------+ | caaca | 2 | caaca → ca|aca → aca → ac|a → ac | +-------+--------+----------------------------------+ | aabaa | 2 | aaba|a → a|aba → ab|a → ab | +-------+--------+----------------------------------+ | abc …

1
精确的机器代码副本运行速度比原始功能慢50%
我一直在尝试从嵌入式系统上的RAM和闪存执行性能。为了快速进行原型制作和测试,我目前使用的是Arduino Due(SAM3X8E ARM Cortex-M3)。据我所知,Arduino运行时和引导程序在这里应该没有任何区别。 这是问题所在:我有一个用ARM Thumb Assembly编写的函数(calc)。calc计算一个数字并将其返回。(对于给定的输入,> 1s运行时)现在,我手动提取了该函数的汇编机器代码,并将其作为原始字节放入另一个函数中。确认这两个功能都驻留在闪存中(地址0x80149和0x8017D紧挨着)。通过反汇编和运行时检查已确认了这一点。 void setup() { Serial.begin(115200); timeFnc(calc); timeFnc(calc2); } void timeFnc(int (*functionPtr)(void)) { unsigned long time1 = micros(); int res = (*functionPtr)(); unsigned long time2 = micros(); Serial.print("Address: "); Serial.print((unsigned int)functionPtr); Serial.print(" Res: "); Serial.print(res); Serial.print(": "); Serial.print(time2-time1); Serial.println("us"); } int calc() { asm …

2
现代PC视频硬件是否在硬件中支持VGA文本模式,或者BIOS是否模拟了它(使用系统管理模式)?
当您在物理线性地址的VGA文本(模式03)帧缓冲器中存储一个字节(例如(0x31))到VGA文本(模式03)时,在以16位旧式BIOS MBR模式引导的现代PC硬件上究竟发生了什么? 将针对该区域的MTRR设置为UC 的商店有多慢? (在一台Kaby Lake iGPU笔记本电脑上进行的实验测试表明,WC上的clflushopt与VGA内存的UC大致相同。但是,如果没有clflushopt,存储到WC内存中的内存永远不会离开CPU,也根本不会更新屏幕,运行速度非常快)'1'B8000mov [es:di], eaxmov 如果不是每个商店的SMI,是否有任何方法可以在用户空间中的WB内存块上近似估算此成本,以进行性能实验而无需实际重新进入实模式?(例如,使用BSS页面作为假装的帧缓冲区,该缓冲区实际上不会显示在任何地方)。 下次刷新时,相应的字形出现在屏幕上,但是硬件扫描真的从VRAM(或iGPU的DRAM)中读取ASCII字符并动态映射到位图字形吗?还是每个存储上都有某个软件拦截或每个vblank拦截一次,以便真正的硬件仅需要处理位图帧缓冲区? 众所周知,传统BIOS引导使用系统管理模式(SMM)将USB kbd /鼠标模拟为PS / 2设备。我想知道它是否也用于VGA文本模式帧缓冲区。我认为它是用于VGA的I /模式的设置O端口,但它是合理的,文本的framebuffer可以通过硬件来支持。但是,大多数计算机将所有时间都花在图形模式上,因此抛弃对文本模式的硬件支持似乎是厂商可能想要做的事情。(OTOH 该博客建议自制的Verilog VGA控制器可以相当简单地实现文本模式。) 我对在Intel Skylake中使用iGPU的系统特别感兴趣,但对Intel和AMD的早期/以后iGPU以及新旧的离散GPU感兴趣。 (包括AMD和NVidia以外的供应商;有些Skylake主板具有PCI插槽,而不是PCIe。如果现代GPU固件驱动程序确实模拟文本模式,则大概是一些旧的PCI视频卡具有硬件VGA文本模式。也许这样的卡可能使商店仅是PCI事务而不是SMI。) 我自己的台式机是华硕Z170 Pro游戏主板中的i7-6700k,没有附加卡,只有在DVI-D输出上具有1920x1200显示器的iGPU。我不知道Kaby Lake i5-7300HQ系统的详细信息@Eldan仅在CPU型号上进行测试。 我从2011年起发现了Phoenix BIOS的专利US20120159520,它 使用uefi模拟旧版视频。他们不要求视频硬件供应商同时提供UEFI 和本机16位实模式选项ROM驱动程序,而是提出了实模式VGA驱动程序(int 10h功能等),该驱动程序通过SMM挂钩调用供应商提供的UEFI视频驱动程序。 摘要 通用视频选项ROM将视频服务请求通知通用视频SMM驱动程序。可以使用软件系统管理中断(SMI)执行此类通知。收到通知后,通用视频SMM驱动程序会将对视频服务的请求通知第三方UEFI视频驱动程序。第三方视频驱动程序向操作系统提供请求的视频服务。以此方式,第三方UEFI图形驱动程序可以支持多种操作系统,即使不是本机支持UEFI显示协议的操作系统。 许多描述涵盖了处理int 10h呼叫和类似已经明显通过IVT捕获的内容,因此可以轻松地运行自定义代码,从而有意触发SMI。相关部分是它们描述的直接存储到文本模式帧缓冲区中的内容,即使对于不触发任何软件或硬件中断的代码,它们也需要工作。(除了硬件在此类商店上触发SMI之外,他们表示可以在支持的情况下使用它们。) 文字缓冲支持 [0066]在某些实施例中,应用程序可以直接操纵VGA的文本缓冲区。在这样的实施例中,通用视频SMM驱动器130以两种方式中的一种来支持这一点,这取决于硬件是否在对740 KB-768 KB存储区域(文本缓冲区所在的位置)的读/写访问时提供SMI陷阱。 [0067]当SMI陷阱可用时,硬件会在每次读取或写入访问时生成一个SMI。使用SMI陷阱的陷阱地址,可以计算出确切的文本列和行,并访问虚拟文本屏幕中的相应行和列。 可替代地,为该区域启用普通存储器,并且使用周期性的SMI,通用视频SMM驱动器130扫描仿真的硬件文本缓冲器中的变化,并更新由视频驱动器维护的相应虚拟文本屏幕。在两种情况下,当检测到更改时,都会在虚拟文本屏幕上重新绘制字符。 这只是BIOS供应商的一项专利,并没有告诉我们大多数硬件的实际工作方式,或者其他供应商是否做不同的事情。但是,它的确确证了存在某些硬件,这些硬件可能会在该范围内的商店中受困。(除非那只是他们决定在其专利中涵盖的一种假设可能性。) 对于我所想到的用例,仅在屏幕刷新上进行捕获要比在每个商店上进行捕获快得多,因此我很好奇哪种硬件/固件以哪种方式工作。 这个问题的动机 在第7代Intel Core上优化视频RAM中的递增ASCII十进制计数器 -将ASCII文本计数器的新数字重复存储到视频RAM的相同字节中。 我在Linux下的WB内存中的32位用户空间中测试了该代码的版本,希望通过movnti每种存储后(或偶尔在计时器中断)。但是,如果实模式引导加载程序情况不只是存储到DRAM,而是触发SMI,这是不现实的。 在WB内存中,用刷新movnti存储lock xor …

2
L2 HW预取器真的有用吗?
我在Whiskey Lake i7-8565U上,分析性能计数器和复制512 KiB数据的时间(是L2缓存大小的两倍),并且对L2 HW预取器的工作遇到了一些误解。 在英特尔手册第4卷MSR中,有MSR 0x1A4的位0用于控制L2硬件预取器(禁用1)。 考虑以下基准: memcopy.h: void *avx_memcpy_forward_lsls(void *restrict, const void *restrict, size_t); memcopy.S: avx_memcpy_forward_lsls: shr rdx, 0x3 xor rcx, rcx avx_memcpy_forward_loop_lsls: vmovdqa ymm0, [rsi + 8*rcx] vmovdqa [rdi + rcx*8], ymm0 vmovdqa ymm1, [rsi + 8*rcx + 0x20] vmovdqa [rdi + rcx*8 + 0x20], ymm1 add …

2
Excel / SharedStrings的排序算法
在Excel中,它们将字符串“压缩”为数字映射(尽管我不确定在这种情况下compress这个词是否正确)。这是下面显示的示例: 虽然这有助于减少总体文件大小和内存占用量,但是Excel如何对字符串字段进行排序?是否每个字符串都需要进行查找映射:如果是这样,这不会大大增加/减慢对字符串字段进行排序的成本(如果有1M的值,则不会进行1M的键查找)不重要的)。关于此的两个问题: 是在Excel应用程序本身中使用共享字符串,还是仅在保存数据时使用共享字符串? 那么在现场排序的示例算法是什么?任何语言都可以(C,C#,C ++,Python)。

1
为什么Raku在多维数组上表现不佳?
我很好奇,为什么Raku在处理多维数组方面表现不佳。我进行了快速测试,使用Python,C#和Raku初始化了二维矩阵,而后面的耗时惊人地长。 对于乐 my @grid[4000;4000] = [[0 xx 4000] xx 4000]; # Elapsed time 42 seconds !! 对于Python table= [ [ 0 for i in range(4000) ] for j in range(4000) ] # Elapsed time 0.51 seconds C# int [,]matrix = new int[4000,4000]; //Just for mimic same behaviour for(int i=0;i<4000;i++) for(int …
10 performance  raku 

1
matplotlib中有没有一种方法可以检查轴的当前显示区域中有哪些艺术家?
我有一个带有互动人物的程序,偶尔会吸引许多艺术家。在此图中,您也可以使用鼠标缩放和平移。但是,在平移缩放期间的性能不是很好,因为每个艺术家总是会被重画。有没有一种方法可以检查当前显示区域中的哪些艺术家并仅重画这些艺术家?(在下面的示例中,性能仍然相对不错,但是可以通过使用更多或更多复杂的艺术家来任意恶化) 我的方法也遇到类似的性能问题hover,无论何时调用它,它都会canvas.draw()在最后运行。但是正如您所看到的,我通过使用缓存和恢复轴的背景(基于此)找到了一种解决方案。这极大地提高了演奏性能,现在即使有许多艺术家,它的运行也非常流畅。也许有一种类似的方法,但是对于panand zoom方法呢? 很抱歉,冗长的代码示例与问题没有直接关系,但对于一个有效的示例来突出此问题是必需的。 编辑 我更新了MWE,使之更能代表我的实际代码。 import numpy as np import numpy as np import sys import matplotlib.pyplot as plt from matplotlib.backends.backend_qt5agg import \ FigureCanvasQTAgg import matplotlib.patheffects as PathEffects from matplotlib.text import Annotation from matplotlib.collections import LineCollection from PyQt5.QtWidgets import QApplication, QVBoxLayout, QDialog def check_limits(base_xlim, base_ylim, new_xlim, new_ylim): if new_xlim[0] …

2
是什么导致Cortex-A72上带有-O0而不是-O3的简单紧密循环的周期如此高的变化?
我正在围绕获取一段代码的高度一致的运行时进行一些实验。我当前正在计时的代码是一个相当随意的CPU约束工作负载: int cpu_workload_external_O3(){ int x = 0; for(int ind = 0; ind < 12349560; ind++){ x = ((x ^ 0x123) + x * 3) % 123456; } return x; } 我已经编写了一个内核模块,该模块禁用中断,然后运行上述功能的10次尝试,通过获取前后时钟周期计数器的差值来计时每次尝试。其他注意事项: 该机器是ARM​​ Cortex-A72,具有4个插槽,每个插槽具有4个内核(每个插槽都有自己的L1缓存) 时钟频率缩放关闭 不支持超线程 机器几乎没有运行,除了一些简单的系统进程 换句话说,我相信大多数/所有系统可变性的原因都可以解决,尤其是当通过禁用了中断的内核模块运行时spin_lock_irqsave(),代码在运行时应该获得几乎相同的性能(可能对性能造成很小的影响)在第一次运行时,首先将某些指令拉入缓存,仅此而已)。 的确,当使用编译基准测试代码时-O3,我平均看到了大约135,845,192个周期中的最多200个周期,并且大多数测试花费的时间完全相同。但是,当使用编译时-O0,范围从262,710,916上升至158,386个周期。范围是指最长和最短运行时间之间的差。而且,对于-O0代码而言,哪个试验是最慢/最快的试验并没有太多的一致性-违反直觉,在某些情况下,最快的试验是最先的,而最慢的试验是在后的! 那么:是什么原因导致-O0代码的可变性如此高的上限?看一下程序集,似乎-O3代码将所有内容(?)存储在寄存器中,而-O0代码中有很多引用sp,因此似乎正在访问内存。但是即使那样,我也希望所有内容都可以放入L1缓存中,并且在确定的访问时间内就可以坐在那里。 码 被基准测试的代码在上面的代码段中。组件在下面。两者都编译时gcc 7.4.0没有标记,除了-O0和-O3。 -O0 0000000000000000 <cpu_workload_external_O0>: 0: d10043ff sub sp, sp, …

4
有没有更快的方法来检查列表中的列表是否等效?
在这里,我有1:7四个不同分区(即{1},{2,3,4},{5,6}和{7})的整数,这些分区写在一个列表中,即list(1,c(2,3,4),c(5,6),7)。我将分区视为集合,这样一个分区内元素的不同排列应被视为同一分区。例如,list(1,c(2,3,4),c(5,6),7)和list(7,1,c(2,3,4),c(6,5))是等效的。 注意,列表中的元素没有重复,例如no list(c(1,2),c(2,1),c(1,2)),因为这个问题正在讨论整个集合的互斥分区。 我在列表中列出了一些不同的排列lst,如下所示 lst <- list(list(1,c(2,3,4),c(5,6),7), list(c(2,3,4),1,7,c(5,6)), list(1,c(2,3,4),7,c(6,5)), list(7,1,c(3,2,4),c(5,6))) 我想做的就是验证所有排列是否相等。如果是,那么我们得到结果TRUE。 到目前为止,我所做的是对每个分区中的元素进行排序,并setdiff()与之一起使用interset()并对其union()进行判断(请参见下面的代码) s <- Map(function(v) Map(sort,v),lst) equivalent <- length(setdiff(Reduce(union,s),Reduce(intersect,s),))==0 但是,我估计每当分区大小扩大时,此方法都将很慢。有什么更快的方法可以做到吗?预先赞赏! 一些测试用例(小数据) # should return `TRUE` lst1 <- list(list(1,c(2,3,4),c(5,6)), list(c(2,3,4),1,c(5,6)), list(1,c(2,3,4),c(6,5))) # should return `TRUE` lst2 <- list(list(1:2, 3:4), list(3:4, 1:2)) # should return `FALSE` lst3 <- list(list(1,c(2,3,4),c(5,6)), list(c(2,3,4),1,c(5,6)), list(1,c(2,3,5),c(6,4)))

1
有什么可以解释这种情况下使用const的开销?
我的头撞在这里的墙上,所以我希望你们中的一些人可以教育我。我当时使用BenchmarkDotNet进行了一些性能基准测试,但遇到了一个奇怪的情况,在该情况下,声明成员似乎const会大大降低性能。 using BenchmarkDotNet.Attributes; using BenchmarkDotNet.Running; using System; namespace PerfTest { [DisassemblyDiagnoser(printAsm: true, printSource: true)] public class Test { private int[] data; private int Threshold = 90; private const int ConstThreshold = 90; [GlobalSetup] public void GlobalSetup() { data = new int[1000]; var random = new Random(42); for (var i = …

3
如何有效地排序R中字符串中的字符?
如何有效地对向量中每个字符串的字符进行排序?例如,给定一个字符串向量: set.seed(1) strings <- c(do.call(paste0, replicate(4, sample(LETTERS, 10000, TRUE), FALSE)), do.call(paste0, replicate(3, sample(LETTERS, 10000, TRUE), FALSE)), do.call(paste0, replicate(2, sample(LETTERS, 10000, TRUE), FALSE))) 我编写了一个函数,该函数将每个字符串拆分为一个向量,对向量进行排序,然后折叠输出: sort_cat <- function(strings){ tmp <- strsplit(strings, split="") tmp <- lapply(tmp, sort) tmp <- lapply(tmp, paste0, collapse = "") tmp <- unlist(tmp) return(tmp) } sorted_strings <- sort_cat(strings) 但是,我需要将其应用到的字符串向量很长,并且此功能太慢。有没有人对如何提高性能有任何建议?
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.