2010-04-27 83 views
16

我有一個程序需要將許多大型一維numpy浮點數組轉換爲分隔字符串。我發現這個操作相對於我的程序中的數學運算相當緩慢,我想知道是否有辦法加速它。例如,考慮以下循環,該循環在numpy數組中使用100,000個隨機數,並將每個數組連接到逗號分隔的字符串中。從1D numpy數組生成分隔字符串的最快方法

import numpy as np 
x = np.random.randn(100000) 
for i in range(100): 
    ",".join(map(str, x)) 

該循環大約需要20秒才能完成(總數,而不是每個循環)。相反,考慮像元素乘法(x * x)這樣的100個週期將花費超過1/10秒的時間來完成。顯然,字符串連接操作會造成很大的性能瓶頸;在我的實際應用中,它將主宰整個運行時間。這讓我想知道,有沒有比「,」更快的方法。join(map(str,x))?由於map()是幾乎所有處理時間發生的地方,這就涉及到是否有更快的方式將大量數字轉換爲字符串。

+1

它是數以字符串所花費的時間的轉換? – Mark 2010-04-27 13:25:35

+0

將兩個整數相乘並轉換/連接100,000個數字是完全不同的事情 - 您怎麼能期望這兩個操作甚至在性能方面處於同一個球場? – 2010-04-27 13:28:00

+0

馬克 - 是的。蒂姆 - 真的。我的觀點是,字符串操作會造成一個真正的瓶頸,如果有辦法加快速度,這將是很好的。 – Abiel 2010-04-27 13:43:36

回答

6

上的各種字符串連接技術在Python中的表現非常好新手必看:http://www.skymind.com/~ocrow/python_string/

我有點驚訝的是,一些後者方法的執行,以及他們這樣做,但看起來你肯定能找到的東西那裏會比你在那裏做的更好。

+0

謝謝sblom。不幸的是,我的代碼已經基本上與提到的最快解決方案相同了。也許沒有辦法讓它變得更快。 – Abiel 2010-04-27 13:45:57

+0

@Abiel如果你真的想要更快,那麼你應該考慮使用Cython。 – 2010-04-27 22:52:19

+2

我認爲當答案解釋要做什麼時,人們會喜歡它,而不只是鏈接到可能會或可能不會在將來被刪除的頁面。 – dbliss 2016-07-15 07:44:43

2

我想你可以用numpy.savetxt傳遞cStringIO.StringIO對象是假文件實驗...

也許使用str(x)和做用逗號替代的空格中(編輯:這不會工作得非常好,因爲str做了一個大數組的省略號:-s)。

因爲這樣做的目的是通過網絡發送數組,所以也許有更好的選擇(在cpu和帶寬上都更高效)。我在其他回答的評論中指出,將數組的二進制表示形式編碼爲Base64文本塊。主要的不便之處在於,讀取大塊數據的客戶端應該能夠做一些令人討厭的事情,比如將一個字節數組重新解釋爲一個浮點數組,這在類型安全的語言中通常是不允許的;但可以通過C庫調用快速完成(大多數語言都提供了這種方法)。

如果你不能混淆位,總有一種處理數字的可能性來將解碼的字節轉換爲浮點數。

哦,並注意通過網絡發送數據時機器的尾數:轉換爲網絡順序 - > base64encode - > send |接收 - > base64decode - >轉換爲主機命令

+0

感謝fortran。不幸的是,我仍然無法使用savetxt或str(x)來提高速度。 str(x)起初似乎要快得多,但是這會消失一次np.set_printoptions(threshold = 100000)(請參閱我對unutbu答案的評論)。 – Abiel 2010-04-27 14:19:52

1

numpy.savetxt甚至比string.join慢。 ndarray.tofile()似乎不適用於StringIO。

但我確實找到了更快的方法(至少適用於OP對例如的python2.5用低版本numpy的的):

import numpy as np 
x = np.random.randn(100000) 
for i in range(100): 
    (",%f"*100000)[1:] % tuple(x) 

它看起來像字符串格式比,如果你有一個字符串join快定義明確的格式,例如在這種特殊情況下。但我想知道爲什麼OP在內存中需要這麼長的一串浮點數。

較新版本的numpy顯示速度沒有提高。

+0

丁格爾 - 無論出於什麼原因,我都沒有發現這比我最初的join和str例子更快。至於爲什麼我需要這些長字符串,我有一個服務器應用程序在numpy數組上運行,然後以純文本字符串分發結果,以便各種客戶端(包括非Python客戶端)可以使用這些數據(這包括髮送通過HTTP到遠程客戶端的數據)。如果有更好的方式來分發數據,我會很樂意使用它,但請記住,使用任何編程語言並在任何操作系統上運行的客戶端都需要能夠使用它。 – Abiel 2010-04-27 15:03:55

+0

對於這種用途,壓縮的二進制數據比純文本更好! :-)現在我的HTTP知識有點生疏,但你至少可以編碼Base64中的原始浮點數以獲得比十進制更好的比特密度。確保編組方案在所有平臺上都相同(檢查網絡和主機字節順序以及IEEE 754兼容表示)。如果沒有numpy的方法去做,你可以在C中編寫你自己的例程並用'ctypes'調用它。 – fortran 2010-04-27 15:24:29

+0

感謝fortran,這看起來可能是答案。當然在numpy中做x.tostring()非常快。我不太熟悉在不同環境下讀寫二進制數據,但我會深入研究這一點。 – Abiel 2010-04-27 16:34:21

0

在OP的代碼中使用itertools中的imap而不是map可以讓我獲得2-3%的改進,但這並不是很多,但可能會與其他想法相結合以提供更多改進。

我個人認爲,如果你想要比這更好,你將不得不使用像Cython這樣的東西。

3

首先將numpy數組轉換爲列表。映射操作似乎在列表上運行速度比在numpy數組上快。

例如

import numpy as np 
x = np.random.randn(100000).tolist() 
for i in range(100): 
    ",".join(map(str, x)) 

在計時測試,我發現一個一致的15%的加速這個例子

我會留給其他人來解釋爲什麼,因爲我不知道這可能會更快!

19

晚了一點,但是這是更快的我:

#generate an array with strings 
x_arrstr = np.char.mod('%f', x) 
#combine to a string 
x_str = ",".join(x_arrstr) 

加快是我的機器上約1.5x

+0

如果你還在附近,@Abiel考慮接受這個答案。 – dbliss 2016-07-15 07:46:07

相關問題