2012-08-16 67 views
2

我使用python設置計算強度的模擬,然後在定製的C擴展中運行它,最後在python中處理結果。在模擬過程中,我想存儲固定長度的浮點數(C雙精度轉換爲PyFloatObjects),它代表每個時間步的變量,但我不知道會提前多少時間步。一旦模擬完成,我需要將結果傳遞迴python,其形式爲記錄每個單獨變量的數據可以作爲類似列表的對象(例如(連續數組的包裝),分段連續陣列或矩陣中有固定步幅的列)。在Python C擴展中記錄未知數量的浮點數

此刻,我創建了一個字典,將每個變量的名稱映射到包含PyFloatObject對象的列表。這種格式非常適合在後期處理階段工作,但我有一種感覺,創作階段可能會快很多。

時間是非常重要的,因爲模擬已經是一個計算繁重的任務。我期望A.購買大量內存和B.明智地設置你的實驗將允許整個日誌適合內存。但是,使用目前的字典列表解決方案將每個變量的日誌保存在連續的內存部分中需要大量的複製和開銷。

我的問題是:什麼是快速記錄千兆字節內存雙倍空間/時間開銷最小的巧妙,低級別的方法,仍然轉化爲一個整潔的Python數據結構?


澄清:當我說 「記錄」,我的意思是保存,直到模擬之後。一旦完成後處理階段,大多數情況下我只會存儲結果圖。所以我實際上並不需要將這些數字存儲在磁盤上。


更新:最後,我改變了我的做法一點,添加日誌(作爲一個字典映射變量名的序列類型)給函數的參數。這允許您傳入諸如列表或數組。陣列或任何具有附加方法的對象。這增加了一點時間開銷,因爲我使用PyObject_CallMethodObjArgs函數來調用Append方法而不是PyList_Append或類似方法。使用數組可以減少內存負載,這看起來是我可以做的最少的編寫我自己擴展的存儲類型的最佳選擇。感謝大家!

+1

你看過numpy嗎?創建一個numpy雙精度數組,而不是PyFloatObjects的正常PyList實際上更容易從C,以及更快的雙方和更高的內存效率。 – abarnert 2012-08-16 21:13:08

+1

另外,您是否確實需要在內存中擁有千兆字節的雙精度,並找到將它們轉儲到磁盤的方法,或者您是否可以首先使用磁盤上的結構? (這可能與雙精度C數組的mmap一樣簡單,您可以通過'struct'模塊從Python解釋)。 – abarnert 2012-08-16 21:14:57

+0

感謝您的建議! Numpy數組雖然是固定大小的,但我只能通過將一個numpy數組圍繞一個C數據塊_after_將其存儲在我使用某種自釀的擴展數組結構自己分配的空間中來有效地執行此操作。我真的很喜歡編寫代碼,但是我想知道C程序員的世代是不是已經比我想出來的東西更快了:) – 2012-08-16 21:18:15

回答

2

您可能想要考慮在Cython中執行此操作,而不是將其作爲C擴展模塊。 Cython非常聰明,可以讓你以一種非常蟒蛇般的方式來做事,儘管它同時允許你使用C數據類型和python數據類型。

您檢出了陣列模塊嗎?它允許您在單個集合中存儲大量標量,同類的類型。

如果您確實在「記錄」這些內容,而不僅僅是將它們返回給CPython,則可以嘗試打開一個文件並對其進行打印。

順便說一句,realloc可能是你的朋友在這裏,無論你使用C擴展模塊還是Cython。

+0

1。我將來肯定會考慮Cython,但我不確定我會獲得值得額外麻煩的速度優勢。 2.陣列模塊看起來像是一個偉大的第一步,甚至可能是最終的答案。謝謝! 3.如果這就是「logging」這個詞的意思,那麼我不記錄它們。如果你知道一個更好的方式來描述我在這裏做什麼,我很樂意聽到它,涉及詞幹「日誌」的谷歌搜索都會導致文本日誌,日誌旋轉和對數的頁面翻頁。 4. realloc是一個很好的朋友,但因爲我想返回一個python對象,所以很可能我不會自己分配。 – 2012-08-16 21:08:56

+0

嗯......儘管我很喜歡使用它,但是陣列模塊似乎沒有C API :-( – 2012-08-21 09:49:09

1

這將是一個更大的思想傾銷而不是一致的答案,因爲它聽起來就是你想要的。如果沒有,我很抱歉。

你在這裏試圖避免的主要問題是在內存中存儲數十億個PyFloatObjects。有幾種方法可以解決這個問題,但它們都是以存儲數十億簡單的C雙精度爲目標,並找到一些方法將它們暴露給Python,就好像它們是PyFloatObjects的序列一樣。

要使Python(或其他人的模塊)完成這項工作,可以在結構模塊或ctypes上使用numpy數組,標準庫數組,簡單的手工包裝器。 (使用ctypes處理擴展模塊有點奇怪,但沒有什麼能阻止你這樣做。)如果你使用的是struct或ctypes,你甚至可以通過創建一個巨大的文件來超越內存的限制,根據需要在窗口中進行映射。

爲了讓你的C模塊做的工作,而不是實際的返回一個列表,返回符合序列協議的自定義對象,所以當有人呼叫,說,FOO。 getitem(i)您將_array [i]轉換爲PyFloatObject。

mmap的另一個優點是,如果您是以迭代方式創建數組,則可以通過流式傳輸到文件來創建它們,然後通過將生成的文件映射回來作爲內存塊來使用它們。

否則,你需要處理的分配。如果您使用的是標準陣列,則需要根據需要自動擴展,但除此之外,您自己正在做。如果需要的話,執行重新分配和複製的代碼並不困難,並且網上有很多示例代碼,但是您必須編寫它。或者您可能要考慮構建一個可以暴露給Python的跨步容器,就好像它是連續的,即使它不是。 (你可以通過複雜的緩衝協議直接做到這一點,但是我個人總是發現比編寫我自己的序列實現更困難。)如果你可以使用C++,vector是一個自動擴展的數組,而deque是一個跨步的容器如果你有SGI STL繩索,它可能是你正在做的事情的更好的步進容器)。

至於對方的回答中指出,用Cython可以幫助一些這方面。沒有太多的「暴露給Python的許多花車」部分;你可以將Python部分移植到Cython中,然後將它們編譯爲C.如果幸運的話,所有需要處理大量浮點的代碼都可以在Cython實現的Python子集內工作,而你需要暴露給實際解釋代碼的唯一東西是更高級別的驅動程序(如果是的話)。

+0

謝謝!您已經清楚地闡明瞭不同的問題:) – 2012-08-16 22:22:10