2014-02-14 27 views
3

注:這不是一個問題 - 我解決了它,並張貼在這裏了,想和大家分享我的經驗教訓。問題得到一個erraneous結果

我遇到過使用numpy的昨晚的一個問題,這裏是我如何簡化爲短代碼。起初它對我來說看起來像一個bug,但是當我試圖寫這個問題時,我意識到這是我自己的錯誤。希望以後也可以從中受益的其他人也能從中受益!

這是對我的Win 7 64重複,以WinSDK 7.1的C編譯器。 Python版本是3.3.3,使用MSC v.1600構建。 Numpy版本是1.8.0。

0)小結:當我通過一個ndarray到我的DLL從C代碼編譯,C代碼看到不同陣列比我傳入

1)寫AC碼:

// testdll.c 
#include <stdlib.h> 

__declspec(dllexport) void copy_ndarray(double *array1, double *array2, size_t array_length); 

void copy_ndarray(double *array1, double *array2, size_t array_length) 
{ 
    size_t i; 
    for(i=0; i<array_length; i++) 
     array2[i] = array1[i]; 
    return; 
} 

2)寫Python代碼:

import numpy as np 
import ctypes 


# wrap the function from dll to python 
lib = ctypes.cdll.LoadLibrary('./testdll.dll') 
fun = lib.copy_ndarray 
fun.restype = None 
fun.argtypes = [np.ctypeslib.ndpointer(ctypes.c_double), np.ctypeslib.ndpointer(ctypes.c_double), ctypes.c_size_t] 
# Initialize array1 and array2 
array_length= 10 
temp = np.c_[100.*np.ones(array_length), 200.*np.ones(array_length)] 
array1 = temp[:, 1] 
array2 = np.zeros(array_length) 
fun(array1, array2, array_length) 

3)運行的代碼。看看array1和array2是如何不同的。

+3

IMO你應該更改標題的東西,看起來像一個實際的問題,或使谷歌搜索友好,讓未來的用戶可以很容易地找到它。 :) –

+0

@ AshwiniChaudhary謝謝!我同意。我已更新它,任何進一步的建議仍然歡迎!此外,我標記爲社區維基可以意識到,不能撤消...你認爲我應該讓它開放,看看別人是否有更好/更乾淨的方式來做到這一點? :) –

+0

其他人仍然可以發佈答案,所以這不是一個問題。 –

回答

3

當然它應該是不同的!

當我使用array1 = temp[:, 1],所述ARRAY1不是一個真正的大小(10,)ndarray。這是尺寸爲(10,2)的temp的視圖。考慮它是如何存儲在內存中的 - 當指針指向c中的另一個sizeof(double)時,它將遇到temp中的下一個元素,而不是array1中的元素。

解決事情是這樣的 - 讀取數據時不使用ndarray觀點!使用此行

array1 = temp[:, 1].copy() 

進行復制,而不是簡單地使用視圖。

正確的Python代碼是:

import numpy as np 
import ctypes 


# wrap the function from dll to python 
lib = ctypes.cdll.LoadLibrary('./testdll.dll') 
fun = lib.copy_ndarray 
fun.restype = None 
fun.argtypes = [np.ctypeslib.ndpointer(ctypes.c_double), np.ctypeslib.ndpointer(ctypes.c_double), ctypes.c_size_t] 
# Initialize array1 and array2 
array_length= 10 
temp = np.c_[100.*np.ones(array_length), 200.*np.ones(array_length)] 
array1 = temp[:, 1].copy() 
array2 = np.zeros(array_length) 
fun(array1, array2, array_length) 

我個人覺得這個棘手的,因爲作爲一個數據分析,99(老實說,我不是...我是一名研究人員,但足夠接近!)視圖優於副本的時間百分比,因爲速度更快,並且無論如何我們都不需要原始的ndarray。

這是很好的學習,並牢記這一點!

+1

你也可以通過'np.frombuffer(temp [:, 1])'看到這個。這會在視圖上調用'PyObject_AsWriteBuffer',在3.x.爲該對象獲取['Py_buffer'](http://docs.python.org/3/c-api/buffer.html#Py_buffer)並返回'buf'指針和'len'。如果它使用'PyObject_GetBuffer',它可以基於'PyBuffer.strides'重建視圖。 – eryksun

+0

@eryksun感謝您對CPython實施的貢獻!這真的很有幫助。 –