2012-02-28 47 views
1

我的應用程序生成了一個大的(> 4GB)數據,我需要遍歷它調用每個數據元素上的python函數。高效使用python對象遍歷調用python函數的大量數據

我的數據將被分解爲「行」,我將定義幾個將引用此數據的python變量(對象)。理想情況下,這些對象將是天然形式,即我的數據將有雙打,整數和焦炭等陣列,即

struct DataRow 
{ 
    char key[ 32 ]; 
    double value; 
    int source; 
}; 
DataRow *rows = new DataRow[ 40000000 ]; 

我讀過一點點的PyBuffer對象可以「包裝」的內存區域上我假設我能夠構建其中的3個以指向第一行數據(鍵,值,源),然後構造一個元組並在代碼對象上調用PyObject_CallObject()早些準備。

PyObject *keyBuffer = PyBuffer_FromMemory(rows[ 0 ].key, 32); 
PyObject *valueBuffer = PyBuffer_FromMemory(&rows[ 0 ].value, sizeof(double)); 
PyObject *sourceBuffer = PyBuffer_FromMemory(&rows[ 0 ].source, sizeof(int)); 

然而,這種做法似乎存在一些問題..

  1. 我如何推進由PyBuffer對象持有指向下一行的指針。
  2. 如何dererence雙和int緩衝區使用python腳本

我敢肯定,這必須是可能裏面thier值。如果不是這樣的話,那麼在所有行中使用python腳本可能會太慢,因爲我必須構建的PyObjects數量太多。

回答

1

如果您想對數據執行任何操作,則不必轉義創建大量python對象。 chars,double和int分別需要成爲不可變的PyString,PyFloat和PyInt對象。

由於您已經在編寫C語言,您還可以創建一個返回一系列鍵/值/源元組的迭代器。

這種方法的好處在於,只要沒有引用保留給這些對象,就可以在連續調用之間重用對象。這可以爲您免除每個對象的分配和釋放。有關如何執行此操作的示例,請參見http://hg.python.org/cpython/file/2.7/Modules/itertoolsmodule.c#l3541的itertools.izip源代碼。我相信這種方法可以在不費很大力的情況下爲您提供所需的效率(只需修改izip代碼即可滿足您的需求)。

+0

我看了一下示例代碼,我不太清楚你在哪裏重用在元組內創建的對象。看起來您正在創建一個新項目,從元組中提取現有項目,用新項目替換現有項目,然後遞減舊項目。這將導致每次「迭代」產生新的對象。你將如何去「重用」這些對象,而不是像你看起來那樣進行替換。 – ScaryAardvark 2012-02-28 14:37:46

+0

@ScaryAardvark在''Py_REFCNT(result)== 1)''的分支中,* result *元組被重用。您可以嘗試更進一步,使用相同的技術重用元組中的每個int/float/str。 – 2012-02-28 18:03:05