小编Max*_*hon的帖子

Python'for'循环的更好方法

我们都知道在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)

python performance time-complexity python-3.x

67
推荐指数
2
解决办法
6307
查看次数

在列表中查找模式

我目前正在寻找一种在整数列表中查找模式的方法,但我将使用的方法适用于字符串和其他具有不同元素的列表.现在让我解释一下我在寻找什么.

我想在整数列表中找到最长的重复模式.例如,

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

python algorithm performance pattern-matching

19
推荐指数
1
解决办法
5322
查看次数

文件读取时创建了不需要的子进程

我正在创建一个多进程程序.当我尝试使用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:我有一个理论,我无法证明它也许你可以帮助我.可能是这样的情况:文件指针在进程之间共享,当子进程退出时,它关闭文件,当父进程再次尝试读取时,它只是从头开始(或其他一些奇怪的行为).可能是这样吗?

c multiprocessing

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

两个字符串中的常用字母数

我使用此代码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)

该解决方案试图找到两个字符串中常见字母的数量(仍然计算相同的字母)我的问题是,我开发了这个逻辑,但我担心它可能是一个轮子重新发明.是否有任何介绍的方法,或更简单的方法吗?

注意:我的问题不同于试图找到字符串之间的常用字母的问题,我只需要计数,所以我希望找到一些基本的东西.

python set venn-diagram

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

为什么平分比排序慢

我知道 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以获得文件读取等行为。并且它非常努力地击败二等分。

python sorting algorithm performance

6
推荐指数
2
解决办法
3278
查看次数

Valgrind在C++代码中显示意外输出

在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:似乎有一个我没有意识到的优化(在评论中说明).谢谢.

c++ memory valgrind stdvector c++11

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

使用基本结构从void *提取值

我的项目中有许多类型的结构,另一个结构包含指向这些结构之一的指针。如,

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 struct

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

当内存池不是一个好主意时避免内存碎片

我正在开发一个 C++ 应用程序,该程序会无限地运行,随着时间的推移分配和释放数百万个字符串 (char*)。RAM的使用是程序中需要认真考虑的因素。这会导致 RAM 使用率随着时间的推移越来越高。我认为问题在于堆碎片。我真的需要找到一个解决方案。

内存使用报告 1

您可以在图中看到,在程序中进行数百万次分配和释放之后,使用量只是在增加。从我测试它的方式来看,我知道它存储的数据并没有增加。我猜你会问,“你怎么确定这一点?”,“你怎么确定这不仅仅是内存泄漏?”,好吧。

在此输入图像描述

这个测试运行的时间要长得多。只要有可能,我就会malloc_trim(0)在我的程序中运行。看来,应用程序最终可以将未使用的内存返回给操作系统,并且它几乎为零(我的程序当前拥有的实际数据大小)。这意味着问题不是内存泄漏。但我不能依赖这种行为,我的程序的分配和释放模式是随机的,如果它从不释放内存怎么办?

  • 我在标题中说过内存池对于这个项目来说是一个坏主意。当然我没有绝对的知识。但我分配的字符串可以是 30-4000 字节之间的任意值。这使得许多优化和聪明的想法变得更加困难。内存池就是其中之一。
  • 我用作GCC 11 / G++ 11编译器。如果某些旧版本的分配器不好。我不应该有这个问题。
  • 我如何获取内存使用情况?Pythonpsutil模块。proc.memory_full_info()[0],这给了我RSS.
  • 当然,你不知道我的程序的细节。如果这确实是由于堆碎片造成的,那么这仍然是一个有效的问题。我可以说的是,我正在保留有关发生了多少分配和释放的最新信息。我知道程序中每个容器的元素计数。但如果您对问题的原因仍然有一些想法,我愿意接受建议。
  • 我不能只是为所有字符串分配 4096 字节,这样优化起来会更容易。这正是我想做的相反的事情。

所以我的问题是,在一个随着时间的推移发生数百万次分配和释放的应用程序中,程序员应该做什么(我应该做什么),并且它们的大小不同,因此内存池很难有效使用。我无法改变程序的作用,我只能改变实现细节。

赏金编辑:当尝试使用内存池时,是否可以创建多个内存池,以便每个可能的字节数都有一个池?例如,我的字符串可能在 30-4000 字节之间。因此,有人不能4000 - 30 + 1为程序的每个可能的分配大小创建 3971 个内存池吗?这不适用吗?所有池都可以从小规模开始(不会损失太多内存),然后扩大,以在性能和内存之间取得平衡。我并不是想利用内存池预先保留大空间的能力。由于频繁的分配和释放,我只是想有效地重用释放的空间。

最后编辑:事实证明,图表中出现的内存增长实际上来自我程序中的 http 请求队列。我没有看到我所做的数十万次测试使这个队列变得臃肿(类似于 webhook)。图 2 的合理解释是,我最终从服务器禁止了 DDOS(或者由于某种原因无法再打开连接),队列清空,RAM 问题解决。因此,以后阅读这个问题的任何人,请考虑每种可能性。我从来没想过会发生这样的事情。不是内存泄漏,而是实现细节。我仍然认为@Hajo Kirchhoff 值得赏金,他的回答确实很有启发性。

c++ memory memory-management fragmentation dynamic-memory-allocation

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

shared_ptr 中 string_view 的返回值优化

很难用语言表达所以我会直接跳到半伪代码中。

我有一个下载函数(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++ optimization object-lifetime return-value-optimization

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

C++ 程序在重新执行时加速

我目前正在对 C++ 程序进行性能测试。我需要批量插入一个std::unordered_map或其他类似的开源结构。我将 30-40 个字符字符串作为键值对插入,并注意到一个有趣的行为。第一次执行代码(Clion)时,花了 20 秒完成,我重复了测试(什么都不做),是 14 秒,然后又是 8 秒、4 秒,代码现在运行大约 3 秒。我应该重复一遍,我的代码中唯一昂贵的操作是批量 unordered_map insert,多线程与std::lock_guard<std::mutex>.

另一个重要的信息是我正在从文件中读取这些键和值。所以我想到了在Ubuntu 中发生的一些文件缓存。但是我用不同的机制做同样的事情,从来没有经历过这样的事情。然后我想到了一些 RAM 分配技巧,可以在程序结束后保持大部分地图完好无损。但我没有做任何事情来实现它。

为什么会这样?不仅如此,我该如何重置?我需要进行客观测试,因为我的代码将在多个服务器中运行,而无需任何预缓存。

谢谢。

c++ ubuntu performance memory-management clion

3
推荐指数
1
解决办法
118
查看次数