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

回答編集履歴

5

追加

2019/04/10 12:23

投稿

YasuhiroNiji
YasuhiroNiji

スコア584

answer CHANGED
@@ -1,4 +1,4 @@
1
- 「Cythonは試してみましたが殆ど速くなりませんでした。」と書いてありますが、以下のようにすべて型を定義すると今回は約2倍早くなりました。C書くのより2倍以上遅いということはないと思います。
1
+ 「Cythonは試してみましたが殆ど速くなりませんでした。」と書いてありますが、以下のようにすべて型を定義すると約2倍早くなりました。1万回の一重ループ内側はnumpyで処理していたでそれぐらいのものだと思います。Cythonで書けばCより2倍以上遅いということはないと思います。
2
2
 
3
3
  ```Cython
4
4
  import cython
@@ -33,6 +33,7 @@
33
33
  ```
34
34
 
35
35
  ```python
36
+ import numpy as np
36
37
  import time as t
37
38
 
38
39
  def main()

4

ミスの修正

2019/04/10 12:23

投稿

YasuhiroNiji
YasuhiroNiji

スコア584

answer CHANGED
@@ -47,7 +47,7 @@
47
47
  main()
48
48
  ```
49
49
 
50
- 計算の最後の部分は、要約すると配列の各要素でその要素より後ろにそれより小さい値があれば1にするということなので、以下のように計算方法を変更すれば1000倍ぐらい速くなります。このロジックが実際に使えるかどうかはわかりませんが、いろいろ方法を試す前にロジックを考えた方がいいと思います。
50
+ 計算の最後の部分は、要約すると配列の各要素でその要素より後ろにそれより小さい値があれば2にするということなので、以下のように計算方法を変更すれば1000倍ぐらい速くなります。このロジックが実際に使えるかどうかはわかりませんが、いろいろ方法を試す前にロジックを考えた方がいいと思います。
51
51
 
52
52
  ```
53
53
  import cython

3

ミスの修正

2019/04/10 12:14

投稿

YasuhiroNiji
YasuhiroNiji

スコア584

answer CHANGED
@@ -28,7 +28,7 @@
28
28
 
29
29
  for j in range(i):
30
30
  if sl[j] > sl[i]:
31
- msk[j] = 1
31
+ msk[j] = 2
32
32
  return msk
33
33
  ```
34
34
 
@@ -79,7 +79,7 @@
79
79
  slmin = sl[n - 1]
80
80
  for j in range(n - 1, -1, -1):
81
81
  if sl[j] > slmin:
82
- msk[j] = 1
82
+ msk[j] = 2
83
83
  else:
84
84
  slmin = sl[j]
85
85
  return msk

2

Cythonのコードを追加

2019/04/10 12:12

投稿

YasuhiroNiji
YasuhiroNiji

スコア584

answer CHANGED
@@ -1,23 +1,86 @@
1
- 「Cythonは試してみましたが殆ど速くなりませんでした。」と書いてありますが、
1
+ 「Cythonは試してみましたが殆ど速くなりませんでした。」と書いてありますが、以下のようにすべて型を定義すると今回は約2倍早くなりました。Cで書くのより2倍以上遅いということはないと思います。
2
- 以下の部分は、配列の各要素でその要素より前にそれより大きい値があれば2にするというだけの計算なので、numpyでは無駄な計算をかなりしているので、Cythonによる処理高速化は可能です。
3
2
 
3
+ ```Cython
4
+ import cython
4
- もし、Cythonで速くならなかったというのならば、そのコードを質問に記載してください。やりかたが間違っているだけです。
5
+ import numpy as np
6
+ cimport numpy as np
5
7
 
8
+ ctypedef np.float64_t np_float_t
9
+ ctypedef np.int32_t np_int_t
10
+
11
+ @cython.boundscheck(False)
12
+ @cython.wraparound(False)
13
+ cpdef np.ndarray[np_int_t, ndim=1] func1(
14
+ np.ndarray[np_float_t, ndim=1] sl,
15
+ np.ndarray[np_float_t, ndim=1] ang):
16
+
17
+ cdef np.ndarray[np_int_t, ndim=1] msk
18
+ cdef int i, j
19
+ cdef int n = len(sl)
20
+ cdef double angmax = ang[0]
21
+
22
+ msk = np.ones(n, dtype='int32')
23
+ for i in range(1, n):
24
+ if angmax > ang[i]:
25
+ msk[i] = 3
26
+ else:
27
+ angmax = ang[i]
28
+
29
+ for j in range(i):
30
+ if sl[j] > sl[i]:
31
+ msk[j] = 1
32
+ return msk
33
+ ```
34
+
6
35
  ```python
7
- csl = sl[0:i+1]
8
- ply = np.where(csl > sl[i])
9
- kly = np.size(ply)
36
+ import time as t
10
- if kly > 0: msk[ply] = 2
11
37
 
38
+ def main()
39
+ start = t.time()
40
+ sl = np.random.rand(10000)
41
+ ang = np.random.rand(10000)
42
+ msk = func1(s1, ang)
43
+ print(msk)
44
+ print('time : ' + str(round((t.time() - start),3)) + ' [sec]')
45
+
46
+ if __name__ == "__main__":
47
+ main()
12
48
  ```
13
49
 
14
- また以下式も間違っていませんか。`msk = np.ones(n)``msk`は全ての要素が1の配列なの、for文の中で msk[i] = 1 しても何もしたことになりませんが。。。
50
+ 計算の最後の部分は要約すると配列各要素の要素より後ろにそれより小さい値あれば1にするいうことなので、以下のよう計算方法を変更すれば1000倍ぐらい速くなります。このロジックが実際に使えるかどうかはわかりませんが、いろいろ方法を試す前にロジックを考えた方がいいと思います
15
51
 
52
+ ```
16
- ```python
53
+ import cython
17
- msk = np.ones(n)
54
+ import numpy as np
55
+ cimport numpy as np
18
56
 
57
+ ctypedef np.float64_t np_float_t
58
+ ctypedef np.int32_t np_int_t
59
+
60
+ @cython.boundscheck(False)
61
+ @cython.wraparound(False)
62
+ cpdef np.ndarray[np_int_t, ndim=1] func2(
63
+ np.ndarray[np_float_t, ndim=1] sl,
64
+ np.ndarray[np_float_t, ndim=1] ang):
65
+
66
+ cdef np.ndarray[np_int_t, ndim=1] msk
67
+ cdef int i, j
68
+ cdef int n = len(sl)
69
+ cdef double angmax = ang[0]
70
+ cdef double slmin
71
+
72
+ msk = np.ones(n, dtype='int32')
19
73
  for i in range(1, n):
20
- maxidx = np.argmax([angmax, ang[i]])
21
- angmax = np.max([angmax, ang[i]])
22
- if maxidx == 0: msk[i] = 1
74
+ if angmax > ang[i]:
75
+ msk[i] = 3
76
+ else:
77
+ angmax = ang[i]
78
+
79
+ slmin = sl[n - 1]
80
+ for j in range(n - 1, -1, -1):
81
+ if sl[j] > slmin:
82
+ msk[j] = 1
83
+ else:
84
+ slmin = sl[j]
85
+ return msk
23
86
  ```

1

修正

2019/04/10 11:02

投稿

YasuhiroNiji
YasuhiroNiji

スコア584

answer CHANGED
@@ -1,7 +1,7 @@
1
1
  「Cythonは試してみましたが殆ど速くなりませんでした。」と書いてありますが、
2
2
  以下の部分は、配列の各要素でその要素より前にそれより大きい値があれば2にするというだけの計算なので、numpyでは無駄な計算をかなりしているので、Cythonによる処理高速化は可能です。
3
3
 
4
- もし、Cythonで速くならなかったというのならば、そのコードを質問に記載してください。やりかたが間違っていのを、Cythonのせいにすのは問題のある発言です。
4
+ もし、Cythonで速くならなかったというのならば、そのコードを質問に記載してください。やりかたが間違っているだけです。
5
5
 
6
6
  ```python
7
7
  csl = sl[0:i+1]
@@ -11,7 +11,7 @@
11
11
 
12
12
  ```
13
13
 
14
- それ以前に、以下の式間違いがありませんか。`msk = np.ones(n)`で`msk`は全ての要素が1の配列なのに、for文の中で msk[i] = 1 としても何もしたことになりませんが。。。
14
+ また、以下の式間違っていませんか。`msk = np.ones(n)`で`msk`は全ての要素が1の配列なのに、for文の中で msk[i] = 1 としても何もしたことになりませんが。。。
15
15
 
16
16
  ```python
17
17
  msk = np.ones(n)