• ベストアンサー

MATLAB 複数のmkdirを実行したい

MATLAB 複数のmkdirを実行したい いつもお世話になります。 matlabにて pass={pass1,pass2,pass3} %pass1~3は文字列が格納されてます。 passnum=1:length(pass) mkdir(pass{passnum}) を実行しようと思ったんですが、引数が多すぎて無理でした。 forループなどを使えば実行出来るんですが、どうにかしてこのような簡易的な書き方で実行出来ないものなんでしょうか? お手数ですがご回答よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • Kules
  • ベストアンサー率47% (292/619)
回答No.4

4度目のKulesです。 >まだ少しだけ締め切らずにおいておきますが、自分でも頑張ってみますので無理なさらないで下さいね。 私自身それほど多くのMatlabの関数を知っているわけではありませんし、 大抵の処理は自分の知っている知識を使って力ずくで書き、 それで問題が発生(時間がものすごくかかるとか、メモリを半端じゃなく使ってメモリ不足と言われるとか) が起きて初めて他の手がないか探すような状況です。 こういった他の人のニーズを見ながら自分の知識を増やすことはマイナスにはなっていないのでご安心を(笑) さて、本題に入ります。 とりあえず今使うデータは、 =====の区切り線 変数がなんやかんや =====の区切り線 データ となってるわけですね? 変数部分は使うんでしょうか? もし使わないなら、 ・fid=fopen('ファイル名');でfidを取得してから、fgetl(fid)で変数の数+2回(=====の行2つ)データを読み捨てる なんかが簡単そうですね。 使うのであれば、今回の場合は(%などなど の行はないものとして扱います) fid=fopen('ファイル名'); textscan(fid,'%[=]'); a=textscan(fid,'wavestart=%d\n'); b=textscan(fid,'waveend=%d\n'); textscan(fid,'%[=]'); c=textscan(fid,'%f'); とすれば aにwavestartの値が、bにwaveendの値が、cに数値がそれぞれセル配列として入ります。 これでどれくらい時間がかかるんですかね…2000万行のdouble値を行列として確保できるかは 知りませんけど。 また、textscanを使っているのなら回数を減らして(500万ずつぐらい)複数回回すと早くなったり するかも。(配列サイズの関係で) 参考になれば幸いです。

aiueoborn
質問者

お礼

毎度ご回答ありがとうございます。 質問2にの所にちょうど補足2つ目を付け足したタイミングで回答を頂けるとは思いませんでした。 投稿時間たった1秒差でしたね。(笑) >こういった他の人のニーズを見ながら自分の知識を増やすことはマイナスにはなっていないのでご安心を(笑) そーいって頂けるなら幸いです。複数回答を頂いてますので手間かけて申し訳ないなぁと思っていたもので。 >変数部分は使うんでしょうか? はい、変数部は使ってます。例えばwavestart waveendは返したい値ですので、 if nargout > 1 .....色々..... .....色々..... if strfind(str, 'wavestart') [a, b, c, wavestart] = strread(str, '%s%s%s%f'); %a b cは wave start = を格納し、wavestartに値を%fで格納。 end; end; ....色々..... ....色々..... if nargout > 2 if strfind(str, 'waveend') [a, b, c, waveend] = strread(str, '%s%s%s%f'); end; という風に各々のデータを出力しています。a b c は使わないので放置してます。 >また、textscanを使っているのなら回数を減らして(500万ずつぐらい)複数回回すと早くなったり >するかも。(配列サイズの関係で) textscanの配列を分解してみるって所が気になったので試みました。 しかし プロパティを調べるとheadlinesで前半スキップは出来るんですが、 textscanを途中で止める方法が分からなく思いつかないので、まだ成功してません。。

その他の回答 (3)

  • Kules
  • ベストアンサー率47% (292/619)
回答No.3

三度Kulesです。 まあ乗りかかった船ってやつですよね(笑) >ところでプロファイラなんて便利な機能があったんですね。 ある程度どこで時間がかかっているのか分かっているならticとtocを使うという手もありますが、 ボトルネックを探すには素直にプロファイラを使うのが早いでしょうね。 fscanfとsaveasですか…どちらもちょっと迷いますね。 ただ1つ言えそうなのはどちらも割りと上流にある関数っぽいということでしょうか (違うかも知れませんが) 先ほど、forループを使わなくてもいいところではforループを使わない方が よいということを書きました。 これはMatlabを高速化する上で1つ重要なテクニックだと思います。 もう1つ高速化するためには、「関数を使い分ける」ということだと思います。 例えば、 reshape(1:10,10,1)と(1:10)'は共に同じものが出来ますが、 実行速度で言えば多分(1:10)'の方が早いと思います。(実際に試したわけではありません) これは、「1行10列の行列を、10行1列に作り替える」よりは「1行10列の行列を転置する」方が 速いだろうという私の予想です。 つまり、「転置」というシンプルな操作を、わざわざ行列を並び替えるreshapeで実現する必要はないよね、ということです。 話を戻します。 fscanf。果たして今実現しようとしているものはfscanfでしかできないのでしょうか?単純に文字列を読み込み、フォーマット指定子で変換していくならtextscanでも出来ます。 数値データで区切り文字が共通ならdlmreadでも読めますし、カンマ区切りならcsvreadも使えます。fgetsや改行が使われているならfgetlでとりあえず文字列として読み込んでしまって、sscanfでフォーマットを指定して読み込んでいくことも出来ます。 これは私の勝手な予想ですが、 fscanfはいくつの数字を読み込むか明示しないため、読み込む先の変数のサイズが動的に確保されていくのだと思われます。Matlabは配列のサイズがどんどん肥大化していくようなプログラムには弱いですし、メモリも使います。例えば、 for k=1::1000; a(k)=k; end; と書く前にa=zeros(1,1000);のように配列のサイズを確定させるだけでも実行速度は変わってきます。 fscanfの特性上このように配列サイズを確定しないまま延々と読み込むので遅くなるのかなあ…と思います。 実際私自身fscanfはあまり使わないですし、使ってもそれほど遅いと感じたことがないのでよくわからないんですが。 あとsaveasですね。これも「何を保存するのか」で使い分けた方がよいと思います。 変数を保存したい場合はsaveが使えますし、画像ファイルを保存したいのならimwriteなんかが使えます。 いろいろ試してみて、今組んでいる内容に相性のいいものを探す作業が必要だと思われます。 以上、参考になれば幸いです。

aiueoborn
質問者

お礼

3度目のご回答ありがとうございます。 長文有り難いです。非常に勉強になります!全く知らないことばかりです。 pngは単なる保存なので、教えて頂けたことをきっかけにどうにか出来そうな気がしてきました。 しかし、fscanfのほうなんですが、現ファイルは ======= wavestart=2 waveend=200000 %などなど。 ======= 3.232 2.221 -0.142 %と言う風にここからdouble値として欲しい値の行が続く。。計約2000万行の数値データ羅列。 といった感じです。そこでKulesさんの文章を頼りに色々調べてみますと textscanが早いようなので、どうにかしてtextscanで読み込んでdoubleで数値を読み込めないか、、と思ってきました。 しかし現データファイルはこのように ==で囲まれたヘッダー部分があるため、 どうすればこれを除いた途中から得ることが出来るのかが、上手くいかないといった状況です。 dlmreadでも同じく===が邪魔してエラーになります。 どうにかしてif文、strfind(str,'===')と組み合わせて出来るかもと思っているんですが、 いかんせん経験不足のためまだ上手くいかない状況です。fgetlなどは-1しかはき出さなくまずは理解からです。 色々書きましたが文章に迷いが出ている通り、現在試行錯誤中です。 それにしても元のコードは何故か[A,count]=fscanf(fid,'%f',inf)で読み込めてるんですよねぇ。。 もっと各コマンドの持つ意味をしっかり理解するべきですね。 まだ少しだけ締め切らずにおいておきますが、自分でも頑張ってみますので無理なさらないで下さいね。 もし上手く行けば補足に書くつもりです。

aiueoborn
質問者

補足

色々試してみました。textscanだとfscanfの場合に比べ読み込みが2倍以上早くなりました。 しかし、一つのセル配列内に2000万行が読み込まれている状態になっていました。 これをどうにかして各行の数値に直せればといった所です。 試してみたのは、簡易的に書くと以下のような流れです。 fid=fopen(filename,'r') str=fgetl(fid) sikiri1=strfind(str,'===') if (sikiri1) while 1 str =fgetl(fid) sikiri2=strfind(str,'===') if sikiri2 break; end end data=textscan(fid,'%f','Delimiter','\n'); おわり。 このfgetlやっとくと、行が進んだ状態から読み込むことが出来るんですね。 これでどうにか数値データのみを抽出し 1×1cell にすることまで出来ました。 あとはこの中に格納されている、2000万×1のdoubleを各行に格納し直すだけで以前のものを再現出来そうです。 残る問題はこの2000万を各行に変換するのにどれだけ時間を要するかですね。 そもそも読み込む際に各行に格納できたら問題無いんですけども。。ちょっと探してみます。

  • Kules
  • ベストアンサー率47% (292/619)
回答No.2

A No.1のKulesです。 なるほど…やはり高速化が目的でしたか。 ただそうなると出てくる疑問は、 「本当にmkdirは計算速度のボトルネックになっているのか?」 ということです。 試しにこんなコードを書いてプロファイラに解析させてみました。 for k=1:300; fname=sprintf('%03d',k); mkdir(fname); end; 所要時間はおおよそ0.286秒(cpu time)、 そのうちmkdirの行に費やした時間は0.08秒です。 mkdirは300回呼び出しているので、 実質1回実行するのに1msかかっていません。 この時間も惜しいぐらいシビアな高速化を行っているのでしょうか? (全体で1秒かからない関数中で、mkdirを1000回以上呼び出すとか) このぐらいは勘弁してあげられないですか?(笑) おそらくここ以外のループ構造が高速化を妨げているのではないかなあ… と思います。 まずは ツール->プロファイラを開く でどこに時間がかかっているのか探すのが先決かと思われます。 (もうされているかもしれませんが) 一般にmatlabはforループを使うと遅いと言われますが、 それなりにパワーのあるPCを使っていればforループの有無による差を そこまで強く感じることはありません。(感じることもありますが) どちらかというと見栄えの問題、プログラムの流れを シンプルに見せる目的 (例えば正方行列A,Bの積を2重のforループで書くと何をしているのか わかりにくいですが←私だけ? MatlabならA*Bの1行で済み、しかも何をしているのかわかりやすい) のような気もします。 で、forループを使わないことで高速化できる場面というのは、 「forループを使わなくても書けるのにforをわざわざ使っているところ」 が圧倒的に多いような気がします。 そこで今回の例を見てみると、関数mkdirはMatlabのヘルプ http://www.mathworks.co.jp/help/ja_JP/techdoc/ref/mkdir.html を見る限り複数フォルダを作るようには出来ていません。 そう考えると、ここを高速化しようと思うと 複数フォルダを生成するmex関数を自分で作るしかないのかなあ… と思います。 ただし、お使いのPCがマルチコア(CPUが2つ以上?)の場合は別です。 Matlabを動作させている時、基本的には1つのCPUしか動作しませんが、 自作関数などを経由させると2つ目のCPUを使い始める時があります。 (私の場合、全ての処理を1つのmファイルに書くとCPU使用率は 最大でも50%ですが、いくつかの処理を関数に分け、別ファイルにして メインの処理から呼びだすようにすることで、CPU使用率を100%にして 処理時間も若干ですが短縮できました) ということで、前回書いたように自作関数を作るというのは高速化の 1つの手段になりうるかも知れません。 長文失礼しました。他にボトルネックになっているところが判明したら、 補足に書いていただければもう少し有用な回答が出来るかも知れません。 参考になれば幸いです。

aiueoborn
質問者

お礼

再びご回答ありがとうございます。 わざわざ試して頂いて助かります。mkdir自体はそんなに時間かからないものなんですね・・ ところでプロファイラなんて便利な機能があったんですね。早速使用して確認してみました。 すると、 fscanfと、図のpngを保存するsaveasのforループの場所が大幅に時間を使っていることが判明しました。 fscanfはASCIIファイルを読み取るために使っています。 fscanfはループさせてませんのでこれ自体が遅いみたいで、改善方法が思いつきませんが、 saveasはmkdirと同じようにforループで実行させてます。なんだか元のmkdirから逸れていて申し訳ありません。

aiueoborn
質問者

補足

補足その2です。 間違い訂正です、2倍じゃなかったです、違う物を見てました。 その読み込み箇所は21秒→16秒に短縮されました。 それでも早くなったのは間違いなさそうです。 あと、cell→行列に でしたが、cell2matというのがあっさり見つかりましたので data=cell2mat(textscan(fid,'%f','Delimiter','\n')); に書き換えたら速度低下なく2000万×1 行列に変換出来ました。 危惧していた変換時間ですがcell2matってのは2000万行あっても0.001秒なんですね。 測定可能単位が0.001までしかなさそうなのでそれ以下かもしれません。 やはりそれ特化のものは素晴らしい性能を持っているようで。。 ちゃんと前とデータの違いがないか確認していませんがおそらく大丈夫そうです。 あとはおっしゃった通り最初に配列を当てるためfgetlで行数を獲得し、 その長さ分先に配列を作ってメモリ確保など、更なる試行していこうと思います。 これ以上は流石に申し訳ないので自分でやってみます。 補足欄で申し訳ないですが改めて、Kulesさんのおかげです。本当に感謝感謝です。

  • Kules
  • ベストアンサー率47% (292/619)
回答No.1

これは…難しい問題ですね。 というのも私自身 for k=1:length(pass); mkdir(pass{k}); end; 以上の回答が思いつかないので(苦笑) ただこうしたくないということは実際のプログラムはもっと長くて、 いちいちforループに入れたくないって感じなんですかね? だとすると後は自作関数ですかね… m_mkdir(pathname)みたいなものを作って、 pathnameが単なる文字列の場合はそのままmkdirに渡して、 pathnameが文字の行列(フォルダ名が全て同じ長さなら行列にすることも可能なので) またはセル配列の時はforループ内でmkdirを複数回実行する、というような 分岐ができる関数にするぐらいでしょうか。 これなら一行でフォルダを複数作成できますね。 「そういうことじゃないんだよ」とかありましたら補足に書いていただければと思います。 あまり役には立たないかも…出直してきます。 参考になれば幸いです。

aiueoborn
質問者

お礼

ご回答ありがとうございます。 質問目的はそれも含みです。今は仕方なくforで回してます。 書き忘れましたがプログラムの高速化が主目的ですので、 forではない書き方で一気に作成は無理なのかなぁと。無理なら無理で諦めつくんですけども。。 mkdirだけの問題ではないんですが、これと似たような箇所がプログラム内に多くありまして、 とりあえずこれが解決できると他の所も同様に改善できるかなと思い、今回質問させて頂きました。 見栄えなら自作関数って手もありますね。多少行数はすっきりしそうです。参考にさせて頂きます。

関連するQ&A

  • MkDir関数

    VBでフォルダを作成する、基本的なロジックを作成しています。 現在、仮にD:\にはフォルダが存在しないとして、 MkDir "D:\Test\Temp\" とするとエラーになってしまいます。 MkDir "D:\Test\" とするとフォルダが作成されるのですが、 その後に、 MkDir "D:\Test\Temp\" とすると、やはりエラーになってしまいます。 どのようにすれば、1つの処理の中で、複数階層のフォルダが作成できるのでしょうか? ちなみにVB6.0 SP5で、実際にはMkDir関数の引数は文字列変数です。 よろしくお願いします。

  • MATLAB ベクトル化(functionの繰り返

    MATLAB Lのプログラムを組んでいます。 for loop では実行時間が長すぎるため、改善したいです。そこでベクトル化を思いつきましたが、「functionの実行を繰り返す」場合の書き方がいまいち分からないので、教えていただきたいです。 元のループ処理は以下の通りです。 for n= 1:length(MeasuredData) SimulatedDataSet(n) = func1(param1(n), param2(n), param3(n)); end 宜しくお願い致します。

  • MATLABでのcsvreadで困っています。

    はじめして。 MATLABの記述方法についての質問です。 Filename = strcat(set_Dialog(1,1),'.csv'); として、Filenameをダイアログから入力できるようにできるようにしました。 ところが、csvread('ファイル名')の引数を文字列として認識させる方法が分かりません。 ご存知の方がいらっしゃいましたら、教えて下さい。 よろしく御願いいたします。

  • プログラム実行時に引数"<"を指定したい。

    自分でも色々調べたのですが、手に負えなかったので質問させていただきます。何度も質問する形になって申し訳ないです。 今取り組んでいる課題の1つに、プログラム実行時に引数として"<"と"ABC"(ABCはファイル名)を指定するとABCに書かれたスクリプトを実行する。というものがあります。 myprogram < scriptfile(←のような感じです) それで、第1引数が"<"なら第2引数のファイルを実行する。というようにしようと思ったのですが、Argv[1]に"<"が格納されません。 引数に"<"を指定すると別の処理をするらしいことは調べたのでわかったのですが、どうにか"<"を格納できないでしょうか?(つまりは、引数が"<"の時とそうでない時で分岐できるようにしたいのです) あと、スクリプトのファイル名もArgv[2]に格納できないんですが、第2引数に指定された文字列はどこへ行ってしまったんでしょうか? 何度もすいませんがよろしくお願いいたします。

  • MATLABのアップグレード問題

    MATLAB初心者です。 MATLAB6.1(おそらく)で開発されたコードがMATLAB7.01で動きません。 アドバイスを頂ければと思います。 1: out = {}; 2: for i=1:length(files), 3: out = [out, helper([d '/' files{i}], pat(2:end))]; 4: end 上記のコードの3行目で「Conversion to cell from char is not possible.」エラーが発生します。 MATLAB6.1から6.5のアップグレード問題で、空のセル配列の連結が原因のようです。 そこで下記のように修正しました。 1: out = {}; 2: for i=1:length(files), 3: if i==1 out = helper([d '/' files{i}], pat(2:end)); 4: else out = [out, helper([d '/' files{i}], pat(2:end))]; 5: end 6: end 1回目のループの場合は連結せず、2回目以降は連結するように修正しています。 このように修正しても意図通り動いていません。 修正方法は間違っていますか。

  • 【C言語教えて下さい!】文字検索

    引数として、複数の文字列を格納した配列、その文字列数、あるいは文字列aを与え、aが複数の文字列を格納した配列中に見つかれば1を返し、見つからなければ0を返す関数find_string()をつくりたいのですがよくわかりません。 どなたかご教授お願いします。 ヒントや考え方など教えて下さい。

  • 【MATLAB】複数stringのarray/vectorの格納方法

    こんにちは。MATLABプログラミングで質問です。 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% >> a = 'cat';b = 'dog'; c = 'pig'; >> list = [a;b;c] list = cat dog pig %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% とリスト化できますが、下の場合、 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% >> a = 'cat';b = 'dog'; c = 'pig';d = 'bird'; >> list = [a;b;c;d] ??? エラー ==> vertcat CAT引数の次元が一致していません %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% dの次元が違いますのでエラーが出ます。 これをまとめるには、 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% >> list(1).str = a;list(2).str = b;list(3).str = c;list(4).str = d; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% でエラーがでなく成功しますが、 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% >> list list = 1x4 struct array with fields: str %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 一括に表示できずに困っています。 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% list = cat dog pig bird %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% と表示させるようなMATLAB string vectorの格納方法はあるでしょうか? なお、最大文字数に合わせてBlankを入れるのは、 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% length(list(1,:)) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% とした時に誤った回答が出ますので、むむむです。

  • javaについて

    ArrayListに格納した16進数(文字列をハッシュ値に変換させた)を引数として文字列照合を行うプログラムを作っています。今までは一文字ずつの照合を行っていたのですがリストごとに照合をしたいです。リストは作ったのですが、引数として入力する際にtoString()を使用してしまうので一文字ずつの比較になってしまいます。またリストの長さを渡したいのに渡された関数の中で.length()の処理を行うのでリストの長さではなく文字の数になってしまいます。どうすればよいのでしょうか…

  • 配列のことでなのですが

    配列で先頭から順番に文字列を格納していきたいのですがどのような方法があるでしょうか? ただforループなどで順番に繰り返すのではなくて、文字列を入力する度に配列の最後尾に文字列を格納していきたいのですが、 例えば for(i=0;i<=10;i++){ scanf("%s",hairetu[i]) } のような方法ではなく配列の中に文字列を前から順番に格納したいです。 詳しい方は知識をかしていただけるとありがたいです。

  • 配列の中に複数存在する数がいくつあるか

    お世話になります。配列の中に同じ数が存在する数がいくつあるかを調べたいのですが、途中でつまづいてしまいました。 例えば配列arrayの中に、0, 0, 5, 0, 5, 1, 5といった数が格納されているとしたら 複数ある数は0と5の2つなので、2を返す、というだけのプログラムです。 int n=array.length; int cnt=0; for(int i=0;i<n;i++){ for(int j=i+1;j<n;j++){ if(array[i]==array[j]){ cnt++; break; } } } return cnt; forループで配列0から同じ数を順番に調べ、もしヒットすればカウントを増やして内側のループをブレイクし、配列1からまた順番に調べようとしたのですが、 上の例の場合、配列0と配列1が同じ数(0)ですので、カウントが余計に増えてしまいます。 どのように組めばうまく動作するでしょうか。宜しくお願いします。

    • ベストアンサー
    • Java

専門家に質問してみよう