【问题标题】:Why does python implementation use 9 times more memory than C?为什么 python 实现使用的内存是 C 的 9 倍?
【发布时间】:2019-03-26 22:37:01
【问题描述】:

我编写了一个程序,在 python 和 C 中创建一个从 2 到用户给定数字的素数列表。我运行这两个程序来寻找相​​同数字的素数,并在活动监视器中查看它们各自的进程。我发现 python 实现使用的内存正好是 C 实现的 9 倍。为什么 python 需要这么多内存,为什么要使用特定的倍数来存储相同的整数数组?以下是该程序的两个实现:

Python 版本:

import math
import sys

top = int(input('Please enter the highest number you would like to have checked: '))
num = 3
prime_list = [2]
while num <= top:
    n = 0
    prime = True
    while int(prime_list[n]) <= math.sqrt(num):
        if num % prime_list[n] == 0:
            prime = False
            n = 0
            break
        n = n + 1
    if prime == True:
        prime_list.append(num)
        prime = False
    num = num + 1
print("I found ", len(prime_list), " primes")
print("The largest prime I found was ", prime_list[-1])

C 版:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/types.h>
#include <unistd.h>

int main(){
    int N;
    int arraySize = 1;
    int *primes = malloc(100*sizeof(int));
    int isPrime = 1;
    primes[0] = 2;
    int timesRealloc = 0;
    int availableSlots = 100;

    printf("Please enter the largest number you want checked: \n");
    scanf("%d", &N);

    int j = 0;
    int i;
    for (i = 3; i <= N; i+=2){
        j = 0;
        isPrime = 1;
        while (primes[j] <= sqrt(i)) {
            if (i%primes[j] == 0) {
                isPrime = 0;
                break;
            }
            j++;
        }
        if (isPrime == 1){
            primes[arraySize] = i;
            arraySize++;
        }
        if (availableSlots == arraySize){
            timesRealloc++;
            availableSlots += 100;
            primes = realloc(primes, availableSlots*sizeof(int));
        }
    }

    printf("I found %d primes\n", arraySize);
    printf("Memory was reallocated %d times\n", timesRealloc);
    printf("The largest prime I found was %d\n", primes[(arraySize-1)]);


    return 0;
}

【问题讨论】:

  • 首先 C 使用汇编语言来执行你的程序,而 Python 使用解释器来执行一些中间代码。 C 中的第二个数组只是内存区域,而在 Python 中它们是(实际上我也不确定)复杂的数据结构。第三,它们可能是没有被垃圾回收的死动态对象。通常,具有丰富类型层次结构和垃圾收集的 OO_languages 比 C 使用更多的内存。
  • Python没有数组,所以不能是“同一个数组”。 C 和 Python 中的 int 类型也有很大不同。
  • @U.Windl 是的,CPython 中的一切都是成熟的对象。 List 对象在底层确实使用了 PyObject 指针的原始数组,但比 C 原始数组要多得多。
  • 优秀的研究顺便说一句!

标签: python c python-3.x memory


【解决方案1】:
>>> import sys
>>> sys.getsizeof(123456)
28

这是 C int 大小的 7 倍。在 Python 3 中,整数是 struct _longobject a.k.a PyLong 的实例:

struct _longobject {
    PyVarObject ob_base;
    digit ob_digit[1];
};

PyVarObject 在哪里

typedef struct {
    PyObject ob_base;
    Py_ssize_t ob_size;
} PyVarObject;

PyObject

typedef struct _object {
    Py_ssize_t ob_refcnt;
    struct _typeobject *ob_type;
} PyObject;

从中,我们得到该对象 123456 在 64 位 Python 构建中的以下内存使用情况:

  • 8 字节用于引用计数器 (Py_ssize_t)
  • 8 字节用于指向类型对象 &amp;PyLong_Type 的指针(类型为 PyTypeObject *
  • 8 个字节用于计算对象可变长度部分的字节数; (Py_ssize_t 类型)
  • 整数中每 30 位数字 4 个字节。

由于 123456 适合前 30 位,因此总计为 28,即7 * sizeof (int)

除了 Python list 中的每个元素都是指向实际对象的 PyObject * 之外;在 64 位 Python 构建中,这些指针中的每一个都是 64 位的;这意味着每个列表元素引用单独消耗的内存是 C int 的两倍。

将 7 和 2 相加得到 9


对于存储效率更高的代码,您可以使用arrays;类型代码'i' 的内存消耗应该非常接近C 版本。 arrays 有 append 方法,因此增长数组应该比在 C / 中使用 realloc 更容易。

【讨论】:

  • OP 可以使用array module 来减少内存使用,在访问时来回转换值以换取速度。
猜你喜欢
  • 2015-02-22
  • 2022-01-04
  • 2014-05-25
  • 2014-11-04
  • 1970-01-01
  • 1970-01-01
  • 2010-09-12
  • 2012-04-01
相关资源
最近更新 更多