質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
AWS Lambda

AWS Lambdaは、クラウド上でアプリを実行できるコンピューティングサービス。サーバーのプロビジョニングや管理を要せず複数のイベントに対してコードを実行します。カスタムロジック用いた他AWSサービスの拡張やAWSの規模やパフォーマンスを用いたバックエンドサービスを作成できます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

3回答

265閲覧

6桁の「1」と「0」のフラグ置換処理の速度を改善させたい

Otazoman

総合スコア44

AWS Lambda

AWS Lambdaは、クラウド上でアプリを実行できるコンピューティングサービス。サーバーのプロビジョニングや管理を要せず複数のイベントに対してコードを実行します。カスタムロジック用いた他AWSサービスの拡張やAWSの規模やパフォーマンスを用いたバックエンドサービスを作成できます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

4クリップ

投稿2019/05/14 10:24

前提・実現したいこと

6桁の1と0のフラグがあって、そのフラグを返却する関数を作成しています。

・フラグが「101100」の場合→関数からの戻り値は「101100」
・フラグが「210110」の場合→関数からの戻り値は「110110」と「0110110」

関数に2が渡された場合はその2を「1」と「0」に置きかえて返すものです。
ひとまず機能は何とか実現できたのですが、ループで処理しているのでフラグが「222222」の様に
すべて「2」で指定された場合の処理時間がかかってしまうため実用に耐えません。
改善策を色々と調べてみましたがこれというアイデアがないため困っております。
どうかお知恵を拝借できますでしょうか。

該当のソースコード

現在のやり方は
1.渡された6桁のフラグを2桁ずつに分解する。
2.2桁に分けたフラグを判定させて新たなフラグを生成する。
例:「22」→「00,10,11,01」
もとのフラグが10の場合は10のままとする。
3.3つに分解したフラグを結合する。
4.付加キーを付加する。

python

1def make_search_key(companycode,searchkey): 2 try: 3 result=[] 4 wh='2' 5 afk=[] 6 sm='' 7 sb='' 8 if searchkey: 9 sf=searchkey[:6] 10 #桁ずれ処理 11 if searchkey[6:9] == '100': 12 sm=searchkey[6:9] 13 sb=searchkey[9:10] 14 else: 15 sm=searchkey[6:8] 16 sb=searchkey[8:10] 17 mf = wh in sf 18 addkey = ['0','1','01','11','001','011','101','111'] 19 if mf: 20 kv1=[] 21 kv2=[] 22 kv3=[] 23 #先頭2桁 24 s1=sf[0:2] 25 if s1 == '02': 26 kv1=['00','01'] 27 elif s1 == '12': 28 kv1=['10','11'] 29 elif s1 == '20': 30 kv1=['00','10'] 31 elif s1 == '21': 32 kv1=['01','11'] 33 elif s1 == '22': 34 kv1=['00','01','10','11'] 35 else: 36 kv1=[s1] 37 #中間2桁 38 s2=sf[2:4] 39 if s2 == '02': 40 kv2=['00','01'] 41 elif s2 == '12': 42 kv2=['10','11'] 43 elif s2 == '20': 44 kv2=['00','10'] 45 elif s2 == '21': 46 kv2=['01','11'] 47 elif s2 == '22': 48 kv2=['00','01','10','11'] 49 else: 50 kv2=[s2] 51 #後ろ2桁 52 s3=sf[4:6] 53 if s3 == '02': 54 kv3=['00','01'] 55 elif s3 == '12': 56 kv3=['10','11'] 57 elif s3 == '20': 58 kv3=['00','10'] 59 elif s3 == '21': 60 kv3=['01','11'] 61 elif s3 == '22': 62 kv3=['00','01','10','11'] 63 else: 64 kv3=[s3] 65 66 print("s1:{0}".format(kv1)) 67 print("s2:{0}".format(kv2)) 68 print("s3:{0}".format(kv3)) 69 70 start = time.time() 71 72 afk=[ i+j+k for i in kv1 for j in kv2 for k in kv3 ] 73 74 elapsed_time = time.time() - start 75 print ("elapsed_time:{0}".format(elapsed_time) + "[sec]") 76 77 if afk: 78 result = [ i+sm+j for i in afk for j in addkey ] 79 return result 80 except Exception as e: 81 print(e) 82 raise e 83

試したこと

処理速度(できれば1秒程度に短縮させたい。)
・3つのうち1つだけに2が1つだけ指定された場合→3秒程度
・3つともに2が1つだけ入っている場合→10秒程度
・全体に2が指定された場合→30秒程度

6桁を合体させた状態でループを減らす様にしてみましたが、やはり「222222」で32パターン程の
フラグを生成することとなり、付加キーを付け加える箇所でパフォーマンスが劣化していました。
そのため速度は改善できませんでした。

CPUの性能を上げれば多少は改善するかと思ってLambdaのスペックを128MBから256MBにしてみたりも
しましたが速度改善はありませんでした。

補足情報(FW/ツールのバージョンなど)

AWS/Lambda
python3.7

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hayataka2049

2019/05/14 11:31

試してみましたが、極めて高速に実行できます。また、質問文に書かれている仕様と異なっている気がします。 None, "101100"を渡す→空リストが返る None, "210110"を渡す→長さ512のリストが返る 仕様を明確にじてください。また、遅いのはこの部分ではなく、他の部分が原因なのでは?
yayakona

2019/05/14 13:57

コードが文章と合っていない気がしてしまうのですが、一旦無視します。 (6桁以外の文字列が返ってくるのは仕様ですか?) 実際に実行してみると爆速だったため確認して見たいことがあります。 私のしょぼい環境でsearchkey="222222"で実行すると elapsed_time:2.6226043701171875e-05[sec] と出力されました。 これを2.6秒と読んでいませんか? 2.6×10の-5乗[秒]のはずなので早いと思います。 間違っていればごめんなさい。
Otazoman

2019/05/15 04:23

>また、質問文に書かれている仕様と異なっている気がします。 if afk:のelse部分が漏れていました。なのでNoneが返ってしまっています。申し訳ありません。 >elapsed_time:2.6226043701171875e-05[sec] >これを2.6秒と読んでいませんか? >2.6×10の-5乗[秒]のはずなので早いと思います。 2.6秒で読んでおりました。すいません。
guest

回答3

0

変換部をワンライナーで書いてみました(itertoolsを使用してますが)

Python

1from itertools import product 2 3target = '00222200' 4 5ret = [target.replace('2','{}').format(*d) for d in product(*[['0','1']]*target.count('2'))] 6#['00000000', '00000100', '00001000', '00001100', '00010000', '00010100', '00011000', '00011100', '00100000', '00100100', '00101000', '00101100', '00110000', '00110100', '00111000', '00111100']

投稿2019/05/15 02:43

magichan

総合スコア15898

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Otazoman

2019/05/15 08:58

1行で行けるのですね。目から鱗です。 pythonまだまだ分からない点がありますが頑張っていきたいと思います。 これからもよろしくお願いいたします。
guest

0

ベストアンサー

関数に2が渡された場合はその2を「1」と「0」に置きかえて返すものです。

任意桁に拡張してみました。当方環境では'2222222222'などでも一瞬で計算が終わります。

Python

1def make_key(key,lst): 2 3 if not key: 4 return lst 5 6 if key[0] == '2': 7 if not lst: 8 lst.append('0') 9 lst.append('1') 10 else: 11 lst0,lst1 = lst[:],lst[:] 12 for i in range(len(lst)): 13 lst0[i] += '0' 14 lst1[i] += '1' 15 lst = lst0 + lst1 16 else: 17 if not lst: 18 lst.append(key[0]) 19 else: 20 for i in range(len(lst)): 21 lst[i] += key[0] 22 23 return make_key(key[1:],lst) 24 25print( make_key('101100',[])) # ['101100'] 26print( make_key('210110',[])) # ['010110', '110110']

なお、提示コードも処理自体にそこまで時間がかかるとは考えにくいです。
ネットワークI/Oなど他の処理に時間がかかっている可能性があります。

投稿2019/05/15 00:38

can110

総合スコア38262

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Otazoman

2019/05/15 08:56

ご回答ありがとうございました。拡張性の部分が非常に参考になりました。 もう一度計測してみたのですが、該当の処理箇所自体は以下の様な感じでした。 処理時間:0.00012135505676269531秒とほぼほぼ影響ない範囲でした。 別の箇所を計測してみると1秒程度を要している箇所がありそこがネックとなっているようなので その箇所について少し突っ込んで確認してみます。 せっかくご教示いただきましたがその箇所が問題個所ではありませんでした。反省です。 将来的な拡張を考えるとこちらの実装の方が断然いいのでベストアンサーとさせていただきます。
Otazoman

2019/05/15 10:06

補足です。原因分かりました。 LambdaからDynamoDBを呼び出す際に上記のフラグを検索に使用しているのですが 222222を指定するとテーブルに存在しないキーまで検索に行ってしまっていて不要な検索に 処理時間を要しているようです。2222の4桁までであればまだ数千の検索なので許容範囲なのですが 222222となると数万単位でヒットしないものの検索まで行っていてそれが原因で処理に時間がかかっていたようです。 1.フラグの中で検索可能フラグ判定ロジックを間に噛ませて検索を制御する。 2.222222の中でありえない禁止のキーの組み合わせを入れておいてそのフラグは返さないようにする。 恐らく、今回は1のロジックで回避せざるを得ないかと考えております。 ご協力ありがとうございました。
can110

2019/05/15 10:12

なるほど、別処理に原因あったのですね。 コメントありがとうございます。 原因分かりスッキリしました。
guest

0

計算量からそれほど負荷になるような演算じゃないとは思うので、単なる思いつき程度ですが、あらかじめdictのリテラルを↓こんなテキトーなんでいいはずなんでローカルで生成して、その辞書から値を引いて使うのはだめですかね?
(パッケージサイズは解凍後サイズで250MBまでらしいんで、空きがあればってことで)

python

1def somefunc(a): 2 return [i + j for i in charToList(a[0]) for j in charToList(a[1])] 3 4def charToList(n): 5 if(n == "0" or n == "1"): 6 return [n] 7 return ["0","1"] 8 9print('{' + ",".join(['"'+str(i)+str(j)+'":["'+ '","'.join(somefunc(str(i)+str(j)))+'"]' for i in range(3) for j in range(3) if 2 in [i, j]]) + '}')

投稿2019/05/14 14:44

papinianus

総合スコア12705

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Otazoman

2019/05/15 08:57

ありがとうございます。関数を呼び出している元の箇所の時間を計測するとネックとなる箇所が 見えてきたのでそちらを確認してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問