欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Cpython3.9源碼解析python中的大小整數(shù)

 更新時(shí)間:2023年04月21日 10:14:09   作者:菜鳥小超  
這篇文章主要介紹了Cpython3.9源碼解析python中的大小整數(shù),在CPython中,小整數(shù)對象池是一種優(yōu)化機(jī)制,用于減少對常用小整數(shù)的內(nèi)存分配和銷毀開銷,需要的朋友可以參考下

小整數(shù)

/* interpreter state */

#define _PY_NSMALLPOSINTS           257
#define _PY_NSMALLNEGINTS           5

這是CPython中定義的兩個(gè)常量,它們用于控制解釋器狀態(tài)中的小整數(shù)對象池。在CPython中,小整數(shù)對象池是一種優(yōu)化機(jī)制,用于減少對常用小整數(shù)的內(nèi)存分配和銷毀開銷。

_PY_NSMALLPOSINTS定義了正小整數(shù)對象池的大小。在這里,其值設(shè)置為257,表示解釋器將為從0到256(包含0和256)的整數(shù)預(yù)分配對象并緩存。這些整數(shù)在很多場景下會(huì)被頻繁使用,所以事先創(chuàng)建并緩存它們可以提高性能。

_PY_NSMALLNEGINTS定義了負(fù)小整數(shù)對象池的大小。在這里,其值設(shè)置為5,表示解釋器將為從-1到-5(包含-1和-5)的整數(shù)預(yù)分配對象并緩存。

在Python解釋器啟動(dòng)時(shí),這些小整數(shù)對象會(huì)被創(chuàng)建并放入對象池。當(dāng)需要這些整數(shù)值時(shí),解釋器會(huì)直接從對象池中獲取對應(yīng)的對象,而不是動(dòng)態(tài)創(chuàng)建新對象。這樣,對于這些小整數(shù)值的操作可以更快地進(jìn)行,節(jié)省了內(nèi)存分配和銷毀的開銷。

static PyObject *
get_small_int(sdigit ival)
{
    assert(IS_SMALL_INT(ival));
    PyThreadState *tstate = _PyThreadState_GET();
    PyObject *v = (PyObject*)tstate->interp->small_ints[ival + NSMALLNEGINTS];
    Py_INCREF(v);
    return v;
}

typedef int32_t sdigit; /* signed variant of digit */

#define IS_SMALL_INT(ival) (-NSMALLNEGINTS <= (ival) && (ival) < NSMALLPOSINTS)

這是get_small_int函數(shù)的實(shí)現(xiàn),它用于從小整數(shù)對象池中獲取一個(gè)指定值的小整數(shù)對象。小整數(shù)對象池包含了一定范圍內(nèi)的整數(shù)對象,主要是為了避免對這些常用的整數(shù)對象進(jìn)行頻繁的內(nèi)存分配和銷毀。

get_small_int函數(shù)接受一個(gè)sdigit類型的參數(shù)ival,表示要獲取的整數(shù)值。在函數(shù)內(nèi)部,首先使用assert(IS_SMALL_INT(ival))確保傳入的整數(shù)值ival在小整數(shù)對象池的范圍內(nèi)。

接下來,函數(shù)獲取當(dāng)前線程狀態(tài)(PyThreadState)并從其中獲取解釋器狀態(tài)(tstate->interp)。解釋器狀態(tài)包含了小整數(shù)對象池,即small_ints數(shù)組。

然后,根據(jù)ival計(jì)算出在small_ints數(shù)組中的索引(ival + NSMALLNEGINTS),并將對應(yīng)位置的對象賦值給v。NSMALLNEGINTS是一個(gè)宏定義,表示負(fù)小整數(shù)的個(gè)數(shù)。假設(shè)我們有一個(gè)整數(shù)值 ival,我們想要在 small_ints 數(shù)組中查找這個(gè)值對應(yīng)的預(yù)分配的小整數(shù)對象。NSMALLNEGINTS 是預(yù)分配的負(fù)數(shù)的數(shù)量。在 CPython 中,NSMALLNEGINTS 的值通常為5,表示有5個(gè)預(yù)分配的負(fù)整數(shù)對象(-1, -2, -3, -4, -5)。

現(xiàn)在,我們將通過計(jì)算 ival + NSMALLNEGINTS 來找到 small_ints 數(shù)組中的索引。例如,假設(shè) ival 為3。那么,我們可以計(jì)算索引如下:

index = ival + NSMALLNEGINTS
index = 3 + 5
index = 8

這意味著 small_ints 數(shù)組中的第8個(gè)元素(從0開始計(jì)數(shù))是我們要查找的整數(shù)對象。在這個(gè)例子中,我們將找到預(yù)分配的小整數(shù)對象3,并將其引用計(jì)數(shù)加1,然后返回這個(gè)對象。

接下來,通過調(diào)用Py_INCREF(v)增加v的引用計(jì)數(shù),以防止對象在其引用計(jì)數(shù)變?yōu)?時(shí)被錯(cuò)誤地回收。

最后,返回指向小整數(shù)對象的指針v。

總之,get_small_int函數(shù)的作用是從小整數(shù)對象池中獲取一個(gè)指定值的小整數(shù)對象,并增加其引用計(jì)數(shù),然后返回該對象。這樣可以提高對常用小整數(shù)的操作性能。

大整數(shù)

/* Long integer representation.
   The absolute value of a number is equal to
        SUM(for i=0 through abs(ob_size)-1) ob_digit[i] * 2**(SHIFT*i)
   Negative numbers are represented with ob_size < 0;
   zero is represented by ob_size == 0.
   In a normalized number, ob_digit[abs(ob_size)-1] (the most significant
   digit) is never zero.  Also, in all cases, for all valid i,
        0 <= ob_digit[i] <= MASK.
   The allocation function takes care of allocating extra memory
   so that ob_digit[0] ... ob_digit[abs(ob_size)-1] are actually available.

   CAUTION:  Generic code manipulating subtypes of PyVarObject has to
   aware that ints abuse  ob_size's sign bit.
*/

這是CPython源碼中關(guān)于長整數(shù)表示的一段注釋。它解釋了PyLongObject如何表示大整數(shù)的絕對值和符號。讓我們逐行分析這個(gè)注釋:

1.首先,注釋指出大整數(shù)的絕對值等于:

SUM(for i=0 through abs(ob_size)-1) ob_digit[i] * 2**(SHIFT*i)

ob_digit表示長整數(shù)的每個(gè)“數(shù)字”,SHIFT是每個(gè)“數(shù)字”的位數(shù),通常為30或15。ob_size表示長整數(shù)的符號和長度,它的絕對值表示長整數(shù)的長度,即“數(shù)字”的個(gè)數(shù)。

2.對于負(fù)數(shù),ob_size小于0。對于0,ob_size等于0。

3.在規(guī)范化的數(shù)中,最高有效位(即最高“數(shù)字”)永遠(yuǎn)不會(huì)為零。此外,在所有情況下,對于所有有效的i,ob_digit[i]的取值范圍在0到MASK之間。MASK的值通常為(1 << PyLong_SHIFT) - 1,即2**PyLong_SHIFT - 1

4.注釋還提到分配函數(shù)負(fù)責(zé)分配額外的內(nèi)存,以確保ob_digit[0]ob_digit[abs(ob_size)-1]實(shí)際上是可用的。

5.最后,注釋中的“警告”部分提醒開發(fā)者,操縱PyVarObject子類型的通用代碼需要注意整數(shù)會(huì)濫用ob_size的符號位。這是因?yàn)?code>ob_size的符號位同時(shí)表示整數(shù)的長度和符號,而通常情況下ob_size僅用于表示長度。

額外解釋

ob_digit 是一個(gè)表示大整數(shù)中每個(gè) “數(shù)字” 的數(shù)組,它是一個(gè)整數(shù)數(shù)組,用于表示長整數(shù)對象(PyLongObject)中的整數(shù)值。每個(gè) “數(shù)字” 都有一個(gè)固定的位數(shù),由 PyLong_SHIFT 定義(通常為 30 或 15)。例如,假設(shè)我們有一個(gè)長整數(shù)對象,其值為 12345678901234567890。

在這個(gè)例子中,假設(shè) PyLong_SHIFT 為 30,這意味著每個(gè) “數(shù)字” 可以表示 2^30 = 1073741824 個(gè)不同的值。為了將這個(gè)大整數(shù)表示為 ob_digit 數(shù)組,我們需要將整數(shù)拆分為基于 2^30 的 “數(shù)字”。在這種情況下,我們可以將整數(shù)表示為:

12345678901234567890 = 4 * 2^(30*2) + 726238597 * 2^(30*1) + 1026062870 * 2^(30*0)

所以,ob_digit 數(shù)組將包含以下元素:

ob_digit[0] = 1026062870
ob_digit[1] = 726238597
ob_digit[2] = 4

在實(shí)際的 CPython 源碼中,PyLongObject 的定義如下:

typedef struct {
    PyObject_VAR_HEAD
    digit ob_digit[1];
} PyLongObject;

在這里,ob_digit 是一個(gè)長度為1的數(shù)組,但實(shí)際上,它是一個(gè)可變長度數(shù)組,根據(jù)所需的 “數(shù)字” 數(shù)量動(dòng)態(tài)分配。要注意的是,當(dāng)一個(gè) PyLongObject 被創(chuàng)建時(shí),會(huì)根據(jù)整數(shù)值的大小動(dòng)態(tài)分配適當(dāng)數(shù)量的空間來存儲 ob_digit 數(shù)組。

總之,ob_digit 是一個(gè)整數(shù)數(shù)組,用于表示長整數(shù)對象中的大整數(shù)值。每個(gè)數(shù)組元素都是一個(gè) “數(shù)字”,具有固定的位數(shù)。這種表示方法使得 CPython 能夠有效地存儲和處理大整數(shù)。

到此這篇關(guān)于Cpython3.9源碼解析python中的大小整數(shù)的文章就介紹到這了,更多相關(guān)Cpython3.9源碼解析大小整數(shù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論