我们都知道在Python中执行语句一定次数的常用方法是使用for循环.
这样做的一般方法是,
# I am assuming iterated list is redundant.
# Just the number of execution matters.
for _ in range(count):
pass
Run Code Online (Sandbox Code Playgroud)
我相信没有人会争辩说上面的代码是常见的实现,但是还有另一种选择.通过乘以引用来使用Python列表创建的速度.
# Uncommon way.
for _ in [0] * count:
pass
Run Code Online (Sandbox Code Playgroud)
还有旧的while方式.
i = 0
while i < count:
i += 1
Run Code Online (Sandbox Code Playgroud)
我测试了这些方法的执行时间.这是代码.
import timeit
repeat = 10
total = 10
setup = """
count = 100000
"""
test1 = """
for _ in range(count):
pass
"""
test2 = """
for _ in [0] …Run Code Online (Sandbox Code Playgroud) 我目前正在寻找一种在整数列表中查找模式的方法,但我将使用的方法适用于字符串和其他具有不同元素的列表.现在让我解释一下我在寻找什么.
我想在整数列表中找到最长的重复模式.例如,
[1, 2, 3, 4, 1, 2, 3]
# This list would give 1, 2, 3
Run Code Online (Sandbox Code Playgroud)
应该丢弃重叠模式.( 不确定 )
[1, 1, 1, 1, 1]
# Should give 1, 1 Not 1, 1, 1, 1
Run Code Online (Sandbox Code Playgroud)
这是什么没有帮助我.
在列表中查找模式(不理解第一个答案背后的逻辑,很少解释.第二个答案只有在解决之前知道模式时才能解决问题.)
从列表中查找整数模式(给出模式并且需要发生的次数.与我的问题不同.)
最常见的子序列问题(大多数人都解决了这个问题,但它并不接近我的.我在搜索模式时需要连续的元素.但是在这个中,单独的元素也算作子序列.)
这是我尝试过的.
def pattern(seq):
n = len(seq)
c = defaultdict(int) # Counts of each subsequence
for i in xrange(n):
for j in xrange(i + 1, min(n, n / 2 + i)):
# Used n / 2 because I figured …Run Code Online (Sandbox Code Playgroud) 我正在创建一个多进程程序.当我尝试使用for循环调用fork()时if(f == 0) break;.我得到了所需数量的子进程.
但是现在,我正在处理输入文件,并且最初不知道所需的进程数.这是我的代码中最小的可能示例.
FILE* file = fopen("sample_input.txt", "r");
while(fscanf(file, "%d", &order) == 1){
f = fork();
if(f == 0){
break;
}
}
Run Code Online (Sandbox Code Playgroud)
例如sample_input.txt:
5 2 8 1 4 2
Run Code Online (Sandbox Code Playgroud)
现在正在创建数千个子进程(我想要6,文件中的整数),可能是什么原因?它与文件指针有关吗?
编辑:我用控制台输出做了一些调试,子进程确实打破了循环.但是,父母一直在阅读一个小文件.如果我删除fork(),循环按预期执行6次.
编辑2:我有一个理论,我无法证明它也许你可以帮助我.可能是这样的情况:文件指针在进程之间共享,当子进程退出时,它关闭文件,当父进程再次尝试读取时,它只是从头开始(或其他一些奇怪的行为).可能是这样吗?
我使用此代码collections Counter来查找两个字符串中的常用字母数.
from collections import Counter
a = "abcc"
b = "bcaa"
answer = 0
ac = Counter(a)
bc = Counter(b)
for key in ac:
answer += min(ac[key], bc[key])
print answer
Run Code Online (Sandbox Code Playgroud)
该解决方案试图找到两个字符串中常见字母的数量(仍然计算相同的字母)我的问题是,我开发了这个逻辑,但我担心它可能是一个轮子重新发明.是否有任何介绍的方法,或更简单的方法吗?
注意:我的问题不同于试图找到字符串之间的常用字母的问题,我只需要计数,所以我希望找到一些基本的东西.
我知道 bisect 使用二分搜索来保持列表排序。但是我做了一个计时测试,这些值正在被读取和排序。但是,与我的知识相反,保留值然后对它们进行排序以高差赢得时机。请更有经验的用户解释这种行为吗?这是我用来测试时间的代码。
import timeit
setup = """
import random
import bisect
a = range(100000)
random.shuffle(a)
"""
p1 = """
b = []
for i in a:
b.append(i)
b.sort()
"""
p2 = """
b = []
for i in a:
bisect.insort(b, i)
"""
print timeit.timeit(p1, setup=setup, number = 1)
print timeit.timeit(p2, setup=setup, number = 1)
# 0.0593081859178
# 1.69218442959
# Huge difference ! 35x faster.
Run Code Online (Sandbox Code Playgroud)
在第一个过程中,我逐个取值,而不是仅仅排序a以获得文件读取等行为。并且它非常努力地击败二等分。
在C++代码的开头,我初始化一个1000000(百万)bool类型数据的向量.但是,在valgrind中,最大堆+堆栈使用量显示为200Kb.鉴于Bool是1字节,不应该是1 Mb?
有没有我没有意识到的优化?或者我错过了什么?
谢谢你的提前.
我使用的是Ubuntu64 16.04系统.编译没有-O参数的代码.
编辑:代码可以简化为此,
vector<bool> * isPrime;
int main(){
isPrime = new vector<bool>(1000000, true);
}
Run Code Online (Sandbox Code Playgroud)
编辑2:似乎有一个我没有意识到的优化(在评论中说明).谢谢.
我的项目中有许多类型的结构,另一个结构包含指向这些结构之一的指针。如,
struct one{int num = 1;};
struct two{int num = 2;};
struct three{int num = 3;};
// These structs hold many other values as well, but the first value is always `int num`.
Run Code Online (Sandbox Code Playgroud)
我还有另一个结构,其中包含对这些结构的引用。我不得不使用,void*因为我不知道将要引用这些结构中的哪个。
struct Holder{void* any_struct};
Run Code Online (Sandbox Code Playgroud)
我的问题是,我需要这些结构中的值,但是我有一个void指针,能否将第一个变量声明为一个基本结构,将其int强制转换,然后使用它num从这些结构中提取变量,例如:
struct Base{int num};
((Base*) Holder->any_struct)->num
// Gives 1, 2 or 3
Run Code Online (Sandbox Code Playgroud) 我正在开发一个 C++ 应用程序,该程序会无限地运行,随着时间的推移分配和释放数百万个字符串 (char*)。RAM的使用是程序中需要认真考虑的因素。这会导致 RAM 使用率随着时间的推移越来越高。我认为问题在于堆碎片。我真的需要找到一个解决方案。
您可以在图中看到,在程序中进行数百万次分配和释放之后,使用量只是在增加。从我测试它的方式来看,我知道它存储的数据并没有增加。我猜你会问,“你怎么确定这一点?”,“你怎么确定这不仅仅是内存泄漏?”,好吧。
这个测试运行的时间要长得多。只要有可能,我就会malloc_trim(0)在我的程序中运行。看来,应用程序最终可以将未使用的内存返回给操作系统,并且它几乎为零(我的程序当前拥有的实际数据大小)。这意味着问题不是内存泄漏。但我不能依赖这种行为,我的程序的分配和释放模式是随机的,如果它从不释放内存怎么办?
GCC 11 / G++ 11编译器。如果某些旧版本的分配器不好。我不应该有这个问题。psutil模块。proc.memory_full_info()[0],这给了我RSS.所以我的问题是,在一个随着时间的推移发生数百万次分配和释放的应用程序中,程序员应该做什么(我应该做什么),并且它们的大小不同,因此内存池很难有效使用。我无法改变程序的作用,我只能改变实现细节。
赏金编辑:当尝试使用内存池时,是否可以创建多个内存池,以便每个可能的字节数都有一个池?例如,我的字符串可能在 30-4000 字节之间。因此,有人不能4000 - 30 + 1为程序的每个可能的分配大小创建 3971 个内存池吗?这不适用吗?所有池都可以从小规模开始(不会损失太多内存),然后扩大,以在性能和内存之间取得平衡。我并不是想利用内存池预先保留大空间的能力。由于频繁的分配和释放,我只是想有效地重用释放的空间。
最后编辑:事实证明,图表中出现的内存增长实际上来自我程序中的 http 请求队列。我没有看到我所做的数十万次测试使这个队列变得臃肿(类似于 webhook)。图 2 的合理解释是,我最终从服务器禁止了 DDOS(或者由于某种原因无法再打开连接),队列清空,RAM 问题解决。因此,以后阅读这个问题的任何人,请考虑每种可能性。我从来没想过会发生这样的事情。不是内存泄漏,而是实现细节。我仍然认为@Hajo Kirchhoff 值得赏金,他的回答确实很有启发性。
c++ memory memory-management fragmentation dynamic-memory-allocation
很难用语言表达所以我会直接跳到半伪代码中。
我有一个下载函数(http GET),它在我的主代码中被多次调用。
std::string download_data(){
std::shared_ptr<HttpResponse> response = some_http_client->send_request("some_link");
return std::string(response->body()); // response->body() is a std::string_view.
}
Run Code Online (Sandbox Code Playgroud)
的http_client,我使用,返回一个shared_ptr作为响应,这个响应(I排除HTTP错误处理的代码中,假定它的200),包含一个response->body(),这是一个std::string_view。
这段代码工作正常,但是,我想确保每次调用/返回此函数时都不会复制下载的数据。
我的主要问题:
return response->body();吗?函数返回后string_view内部是否shared_ptr有效?我考虑过的事情,或者在我的代码的旧版本中使用过的事情:
std::string(使用另一个std::string作为正文返回的 http 客户端)。std::move.response->body,避免返回(我讨厌它)。这样做的正确方法是什么?
我的工具链:
Ubuntu 20.04 ( GLIBC 2.31), g++ 10.2, C++20.
我目前正在对 C++ 程序进行性能测试。我需要批量插入一个std::unordered_map或其他类似的开源结构。我将 30-40 个字符字符串作为键值对插入,并注意到一个有趣的行为。第一次执行代码(Clion)时,花了 20 秒完成,我重复了测试(什么都不做),是 14 秒,然后又是 8 秒、4 秒,代码现在运行大约 3 秒。我应该重复一遍,我的代码中唯一昂贵的操作是批量 unordered_map insert,多线程与std::lock_guard<std::mutex>.
另一个重要的信息是我正在从文件中读取这些键和值。所以我想到了在Ubuntu 中发生的一些文件缓存。但是我用不同的机制做同样的事情,从来没有经历过这样的事情。然后我想到了一些 RAM 分配技巧,可以在程序结束后保持大部分地图完好无损。但我没有做任何事情来实现它。
为什么会这样?不仅如此,我该如何重置?我需要进行客观测试,因为我的代码将在多个服务器中运行,而无需任何预缓存。
谢谢。
c++ ×4
performance ×4
python ×4
algorithm ×2
c ×2
memory ×2
c++11 ×1
clion ×1
optimization ×1
python-3.x ×1
set ×1
sorting ×1
stdvector ×1
struct ×1
ubuntu ×1
valgrind ×1
venn-diagram ×1