回答編集履歴

3

高速化する方法を提案

2021/04/13 16:48

投稿

Hey_CH
Hey_CH

スコア437

test CHANGED
@@ -1,6 +1,8 @@
1
1
  どういう風に使いたいか不明なので、勘ですが。
2
2
 
3
3
  C#から取得したbyte配列をpython側で2byte(16ビット)のint配列として扱えるよう修正[2021/04/13 10:31]
4
+
5
+ 高速化方法を見つけたので修正[2021/4/14 01:46]
4
6
 
5
7
  ```C#
6
8
 
@@ -14,13 +16,11 @@
14
16
 
15
17
  public int testroc(ref byte[] bArray) {
16
18
 
17
- bArray[0] = 0x00;
19
+ for (int i = 0; i < bArray.Length; i++) {
18
20
 
19
- bArray[1] = 0x01;
21
+ bArray[i] = (byte)(i % 0xff);
20
22
 
21
- bArray[2] = 0xff;
23
+ }
22
-
23
- bArray[3] = 0xff;
24
24
 
25
25
  return 1;
26
26
 
@@ -30,29 +30,101 @@
30
30
 
31
31
  }
32
32
 
33
+
34
+
33
35
  ```
34
36
 
35
37
  dllは「TestLibraryForPython.dll」とする
38
+
39
+ 不要なprintやコメントは削除してください。
36
40
 
37
41
  ```python
38
42
 
39
43
  import clr
40
44
 
45
+ #import numpy as np
46
+
47
+ import datetime , struct
48
+
41
- clr.AddReference("TestLibraryForPython")
49
+ clr.AddReference('TestLibraryForPython')
42
50
 
43
51
  from testNameSpace import testClass
44
52
 
45
53
 
46
54
 
55
+ def bytes_to_intarray(arr):
47
56
 
48
-
49
- def bytes_to_intarray(arr):
57
+ """#for文を使った場合(遅い)
50
58
 
51
59
  result = []
52
60
 
53
61
  for i in range(0,len(arr),2):
54
62
 
55
- result.append(arr[i]<<8 | arr[i+1]) #Big Endian
63
+ #result.append(arr[i]<<8|arr[i+1]) #18秒くらい
64
+
65
+ result.append(int.from_bytes([arr[i] , arr[i+1]] , 'big', signed='False')) #22秒くらい
66
+
67
+ """
68
+
69
+
70
+
71
+ """#リストの内包表記を使った場合(遅い)
72
+
73
+ #result = [arr[i]<<8|arr[i+1] for i in range(0,len(arr),2)] #18秒くらい
74
+
75
+ result = [int.from_bytes([arr[i] , arr[i+1]] , 'big', signed='False') for i in range(0,len(arr),2)] #22秒くらい
76
+
77
+ """
78
+
79
+
80
+
81
+ #struct.unpackを使った場合(Python.NETのメーリングリスト?からコピペ)
82
+
83
+ from ctypes import string_at
84
+
85
+ from System.Runtime.InteropServices import GCHandle, GCHandleType
86
+
87
+ arr_hndl = GCHandle.Alloc(arr, GCHandleType.Pinned)
88
+
89
+ try:
90
+
91
+ arr_ptr = arr_hndl.AddrOfPinnedObject().ToInt64() #32bit CPUの場合(.ToInt32())
92
+
93
+ fmt = '>' + str(int(len(arr)/2)) + 'H' #Big endianで2byteの符号なし整数 arrの長さが500の場合:'>250H'
94
+
95
+ result = struct.unpack(fmt, string_at(arr_ptr, len(arr))) #formatは公式ドキュメントに書いてある
96
+
97
+ finally:
98
+
99
+ if arr_hndl.IsAllocated: arr_hndl.Free()
100
+
101
+
102
+
103
+ """#NumPyを使った場合(importのコメントを外して使う)
104
+
105
+ from ctypes import string_at
106
+
107
+ from System.Runtime.InteropServices import GCHandle, GCHandleType
108
+
109
+ arr_hndl = GCHandle.Alloc(arr, GCHandleType.Pinned)
110
+
111
+ try:
112
+
113
+ arr_ptr = arr_hndl.AddrOfPinnedObject().ToInt64() #32bit CPUの場合(.ToInt32())
114
+
115
+ #dtypeはここがわかりやすい→https://note.nkmk.me/python-numpy-dtype-astype/
116
+
117
+ #>←はバイトオーダー(Big endian)
118
+
119
+ result = np.frombuffer(string_at(arr_ptr, len(arr)),'>u2')
120
+
121
+ finally:
122
+
123
+ if arr_hndl.IsAllocated: arr_hndl.Free()
124
+
125
+ """
126
+
127
+
56
128
 
57
129
  return result
58
130
 
@@ -62,28 +134,44 @@
62
134
 
63
135
  test = testClass()
64
136
 
65
- bs = bytes(range(4))
137
+ bs = bytes(50000000)
66
138
 
67
139
 
68
140
 
141
+ """#これは4秒くらいでできる
142
+
69
- r = test.testroc(bs)
143
+ t0 = datetime.datetime.now()
144
+
145
+ for b in bs:
146
+
147
+ b+=1;
148
+
149
+ t1 = datetime.datetime.now()
150
+
151
+ print(t1-t0)
152
+
153
+ """
70
154
 
71
155
 
72
156
 
157
+ r = test.testroc(bs) #bsのサイズがでかくなるとこれが呼ばれるまでに時間がかかる。C#用に何かやってる?
158
+
73
159
  bs = r[1]
74
-
75
- print(str(bs))
76
-
77
- for b in bs:
78
-
79
- print(type(b),isinstance(b,int),b+0xff)
80
160
 
81
161
 
82
162
 
163
+ t2 = datetime.datetime.now()
164
+
83
165
  bs2 = bytes_to_intarray(bs)
84
166
 
85
- print(bs2)
167
+ t3 = datetime.datetime.now()
86
168
 
169
+ print('bytes_to_intarray時間:',t3-t2)
87
170
 
171
+ print('変換後のサイズ:',len(bs2))
172
+
173
+ for i in range(0,10):
174
+
175
+ print(type(bs2[i]), struct.pack('>H',bs2[i]))
88
176
 
89
177
  ```

2

表現が間違っていたため修正16進数→2byte(16ビット)

2021/04/13 16:48

投稿

Hey_CH
Hey_CH

スコア437

test CHANGED
@@ -1,6 +1,6 @@
1
1
  どういう風に使いたいか不明なので、勘ですが。
2
2
 
3
- C#から取得したbyte配列をpython側で16進数のint配列として扱えるよう修正[2021/04/13 10:31]
3
+ C#から取得したbyte配列をpython側で2byte(16ビット)のint配列として扱えるよう修正[2021/04/13 10:31]
4
4
 
5
5
  ```C#
6
6
 

1

byte配列をint16として扱うよう修正

2021/04/13 01:33

投稿

Hey_CH
Hey_CH

スコア437

test CHANGED
@@ -1,4 +1,6 @@
1
1
  どういう風に使いたいか不明なので、勘ですが。
2
+
3
+ C#から取得したbyte配列をpython側で16進数のint配列として扱えるよう修正[2021/04/13 10:31]
2
4
 
3
5
  ```C#
4
6
 
@@ -12,11 +14,13 @@
12
14
 
13
15
  public int testroc(ref byte[] bArray) {
14
16
 
15
- bArray[0] = 0;
17
+ bArray[0] = 0x00;
16
18
 
17
- bArray[1] = 1;
19
+ bArray[1] = 0x01;
18
20
 
19
- bArray[2] = 2;
21
+ bArray[2] = 0xff;
22
+
23
+ bArray[3] = 0xff;
20
24
 
21
25
  return 1;
22
26
 
@@ -40,9 +44,25 @@
40
44
 
41
45
 
42
46
 
47
+
48
+
49
+ def bytes_to_intarray(arr):
50
+
51
+ result = []
52
+
53
+ for i in range(0,len(arr),2):
54
+
55
+ result.append(arr[i]<<8 | arr[i+1]) #Big Endian
56
+
57
+ return result
58
+
59
+
60
+
61
+
62
+
43
63
  test = testClass()
44
64
 
45
- bs = bytes(range(3))
65
+ bs = bytes(range(4))
46
66
 
47
67
 
48
68
 
@@ -56,18 +76,14 @@
56
76
 
57
77
  for b in bs:
58
78
 
59
- print(str(b))
79
+ print(type(b),isinstance(b,int),b+0xff)
60
80
 
61
81
 
62
82
 
63
- bs2 = bytes(bs)
83
+ bs2 = bytes_to_intarray(bs)
64
84
 
65
- print(str(bs2))
85
+ print(bs2)
66
86
 
67
87
 
68
88
 
69
- for b in bs2:
70
-
71
- print(str(b))
72
-
73
89
  ```