質問するログイン新規登録

回答編集履歴

5

追記

2018/10/19 18:37

投稿

hayataka2049
hayataka2049

スコア30939

answer CHANGED
@@ -79,8 +79,8 @@
79
79
  for(i=0; i < nh; i++) {
80
80
  result16[i] = buf16[i] >> 8 | buf16[i] << 8;
81
81
  }
82
+
82
83
  result = (char *)result16;
83
-
84
84
  return result;
85
85
  }
86
86
 
@@ -89,4 +89,22 @@
89
89
  }
90
90
  ```
91
91
 
92
- ただpythonオブジェクトへの変換に相当のオーバーヘッドがあるようですね。
92
+ ただpythonオブジェクトへの変換に相当のオーバーヘッドがあるようですね。
93
+
94
+ あと、インターフェースを多少整えました。
95
+
96
+ **convmod.py**
97
+ ```python
98
+ import ctypes
99
+
100
+ cptr = ctypes.POINTER(ctypes.c_char)
101
+ lib = ctypes.cdll.LoadLibrary('./conv.so')
102
+ lib.convert.restype = cptr
103
+ lib.convert.argtypes = (ctypes.c_int, cptr)
104
+
105
+ def conv(b_input):
106
+ n = len(b_input)
107
+ result = lib.convert(n, b_input)[:n]
108
+ lib.free_result()
109
+ return result
110
+ ```

4

更に追記

2018/10/19 18:37

投稿

hayataka2049
hayataka2049

スコア30939

answer CHANGED
@@ -51,11 +51,42 @@
51
51
  print(result) # => b'\x01\x00\x03\x02'
52
52
  ```
53
53
 
54
- ### 追記
54
+ ### 追記2
55
55
  ```python
56
56
  def conv_np(b_input):
57
57
  npa = np.frombuffer(b_input, dtype=np.int16).copy()
58
58
  return npa.byteswap(inplace=True).tobytes()
59
59
  ```
60
60
 
61
- こんなのと速度を比較したら、顕著な速度差がなかったことを申し添えておきます。悲しい。
61
+ こんなのと速度を比較したら、顕著な速度差がなかったことを申し添えておきます。悲しい。
62
+
63
+ ### 追記3
64
+ ビットシフトで書き直して、なんとかnumpyより速くなりました。
65
+
66
+ ```C
67
+ #include <stdlib.h>
68
+ #include <stdint.h>
69
+
70
+ char *result;
71
+
72
+ char *convert(int n, char *buf){
73
+ int i, nh;
74
+ uint16_t *result16, *buf16;
75
+
76
+ result16 = (uint16_t *)malloc(sizeof(char)*n);
77
+ buf16 = (uint16_t *)buf;
78
+ nh = n/2;
79
+ for(i=0; i < nh; i++) {
80
+ result16[i] = buf16[i] >> 8 | buf16[i] << 8;
81
+ }
82
+ result = (char *)result16;
83
+
84
+ return result;
85
+ }
86
+
87
+ void free_result(void) {
88
+ free(result);
89
+ }
90
+ ```
91
+
92
+ ただpythonオブジェクトへの変換に相当のオーバーヘッドがあるようですね。

3

もう少し追記

2018/10/19 18:27

投稿

hayataka2049
hayataka2049

スコア30939

answer CHANGED
@@ -49,4 +49,13 @@
49
49
  result = lib.convert(n, b_input)[:n]
50
50
  lib.free_result()
51
51
  print(result) # => b'\x01\x00\x03\x02'
52
- ```
52
+ ```
53
+
54
+ ### 追記
55
+ ```python
56
+ def conv_np(b_input):
57
+ npa = np.frombuffer(b_input, dtype=np.int16).copy()
58
+ return npa.byteswap(inplace=True).tobytes()
59
+ ```
60
+
61
+ こんなのと速度を比較したら、顕著な速度差がなかったことを申し添えておきます。悲しい。

2

メモリ管理

2018/10/19 17:31

投稿

hayataka2049
hayataka2049

スコア30939

answer CHANGED
@@ -10,8 +10,9 @@
10
10
  ```C
11
11
  #include <stdlib.h>
12
12
 
13
+ char *result;
14
+
13
15
  char *convert(int n, char *buf){
14
- char *result;
15
16
  int i;
16
17
 
17
18
  result = (char *)malloc(sizeof(char)*n);
@@ -23,6 +24,10 @@
23
24
 
24
25
  return result;
25
26
  }
27
+
28
+ void free_result(void) {
29
+ free(result);
30
+ }
26
31
  ```
27
32
 
28
33
  **コンパイルコマンド**
@@ -42,6 +47,6 @@
42
47
  b_input = b'\x00\x01\x02\x03'
43
48
  n = len(b_input)
44
49
  result = lib.convert(n, b_input)[:n]
45
-
50
+ lib.free_result()
46
51
  print(result) # => b'\x01\x00\x03\x02'
47
52
  ```

1

追記

2018/10/19 16:29

投稿

hayataka2049
hayataka2049

スコア30939

answer CHANGED
@@ -1,3 +1,47 @@
1
1
  高速性を重視するなら、Cで書いてpythonからwrapして使うというのはどうでしょうか。
2
2
 
3
- [16.16. ctypes — Pythonのための外部関数ライブラリ — Python 3.6.5 ドキュメント](https://docs.python.jp/3/library/ctypes.html)
3
+ [16.16. ctypes — Pythonのための外部関数ライブラリ — Python 3.6.5 ドキュメント](https://docs.python.jp/3/library/ctypes.html)
4
+
5
+
6
+ ### 追記
7
+ 書いてみました。私もctypesには慣れていないので、確実な動作は保証しません。変なところがあれば、極力修正はするつもりです。
8
+
9
+ **conv.c**
10
+ ```C
11
+ #include <stdlib.h>
12
+
13
+ char *convert(int n, char *buf){
14
+ char *result;
15
+ int i;
16
+
17
+ result = (char *)malloc(sizeof(char)*n);
18
+
19
+ for(i=0; i < n; i+=2) {
20
+ result[i] = buf[i+1];
21
+ result[i+1] = buf[i];
22
+ }
23
+
24
+ return result;
25
+ }
26
+ ```
27
+
28
+ **コンパイルコマンド**
29
+ ```
30
+ $ gcc -shared -fPIC conv.c -o conv.so
31
+ ```
32
+
33
+ **conv_test.py**
34
+ ```python
35
+ import ctypes
36
+
37
+ cptr = ctypes.POINTER(ctypes.c_char)
38
+ lib = ctypes.cdll.LoadLibrary('./conv.so')
39
+ lib.convert.restype = cptr
40
+ lib.convert.argtypes = (ctypes.c_int, cptr)
41
+
42
+ b_input = b'\x00\x01\x02\x03'
43
+ n = len(b_input)
44
+ result = lib.convert(n, b_input)[:n]
45
+
46
+ print(result) # => b'\x01\x00\x03\x02'
47
+ ```