HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2011
0216
youtnoteload53解決


yout

リンク

2011/2/16(Wed) 17:31:06|NO.37142

500MB程度のテキストファイルをsdimした上でnoteloadしようとすると、
プログラムがエラーで停止します。
(HSP側でなく、Win側から報告するかと。)
解決法を示してください。



この記事に返信する


ORZ

リンク

2011/2/16(Wed) 18:16:27|NO.37143

ご質問なされる御身分の御方がそのような口調で事をのたまうと
回答者一同恐縮してしまいかえって返信がつかないのではないかと思われます。
無礼を承知で申し上げますと、「教えてくださいよろしくお願いします」と書き添えたり
実際に動作するコードを張り付けたり、貴方のPCの搭載メモリ量などを提示したほうが
真っ当な返信がつくと思います。



f3dx

リンク

2011/2/17(Thu) 08:33:48|NO.37148

普通はメモリにロードせんでファイルマッピングちゅうのおつかうんやけどな



ひらまる

リンク

2011/2/17(Thu) 14:03:59|NO.37150

>ファイルマッピング
もしかしてあれですか、
ファイルの読込インデックスと、読み込むサイズを指定する奴ですか。
なるほど。こういう場合に使うのですね。勉強になります。
ま、僕質問者じゃないんですけど(・ω・)



ひよこ

リンク

2011/2/17(Thu) 17:53:52|NO.37151

>ひらまる
  多分ファイルマッピングについて誤解していると思います。
 あなたが言っているのはbload命令のことではないでしょうか。
 あなたもファイルマッピングについて自信がないようですし、
 勝手に解釈せず、ちゃんとググるなりしましょう。
 "http://www.google.co.jp/search?q=ファイルマッピング"

>yout
  「示してください」と言われちゃ示さずにレスするわけにはいきませんね。
  
  ファイルマッピング、別名メモリ・マップト・ファイルとは、
 これは本来別の二つのプロセス間でメモリを共有するためのもので、
 ファイルを仮想メモリにマップすることです。
 その仮想メモリにアクセスして書き換えなどすると、
 自動的にファイル本体が書き換えられます。
 
  それを行えばバッファにファイルをロードし、
 それをセーブするということをせずに済むので、
 大きなサイズのファイルアクセスの効率化、
 またこのnoteload問題を解決することができます。
 
  質問は、せめて「示していただけませんか」ぐらいにしませんか。

参考 : http://itpro.nikkeibp.co.jp/article/COLUMN/20071107/286607/



yout

リンク

2011/2/17(Thu) 19:15:18|NO.37152

言葉遣い失礼しました。


#runtime "hsp3cl" sdim Primes,507044545 notesel Primes noteload "prime10.txt" mes Primes stop

WinXp 32bit
Mem 1GB

ファイルマッピングの方法を教えてください。



ひよこ

リンク

2011/2/17(Thu) 20:27:02|NO.37155

すいません。さっきの参考URLは会員登録が必要でしたね。
参考(改) : http://tokyo.cool.ne.jp/chokuto/advanced/sharedmem.html

簡単に言うと、ファイルマッピングの流れはこんな感じです。
まずCreateFile関数で取得したファイルハンドルを
CreateFileMapping関数に渡し、ファイルマッピングオブジェクトを作成します。
成功したら、MapViewOfFile関数でマップし、マップされたアドレスが返されますので、
それを変数に割り当て、ファイルの編集を変数の編集により行います。
(メイン作業)
作業が終わり、ファイルを使う必要がなくなったら、
UnmapViewOfFile関数、CloseHandle関数で、アンマップ、ハンドル解放をします。


たぶん読んでもあまり伝わらないと思います。説明下手なもので。
細かいところ、分からないところは参考URLをみてください。



ひらまる

リンク

2011/2/17(Thu) 23:29:20|NO.37164

>ひよこさん
詳しい説明ありがとうございます。
つまりファイルマッピングというのは、
ハードディスクに存在するファイルを、
メモリ上に存在するデータのように扱う機能ということでしょうか。

いわゆる、「ファイルが使用中なのでアクセスできません」っていう奴ですか!!!
色々読んだり試したりしてみます。 ありがとうございました!



ひよこ

リンク

2011/2/17(Thu) 23:48:03|NO.37166

>ひらまるs
 誠に申し上げにくいのですが、後半のほうちょっと違います。
 前半(1〜5行目)は全くその通りです。
 ただ、「ファイルが使用中なのでアクセスできません」については、
 ファイルマッピングをした場合に出る場合があるというのに相違はないのですが、
 これはファイルマッピングにかぎらず、他プロセスのファイルアクセス拒否の場合は出ます。
 
 たとえばさっきの説明で、
 ファイルマップ(CreateFileMapping〜UnmapViewOfFile関数)の部分をぬかしても、
 CreateFileで他のプロセスがアクセスできないように第三引数で0を指定し、
 排他ロックをかけるだけで、他プロセスのファイルアクセスを拒否できます。
 また、ファイルマッピングをしたとしてもCreateFileで排他ロックをかけなければきっと
 ダイアログは出ません。(試してないので間違ってたらすいません。)

 つまり、「ファイルが使用中なのでアクセスできません」はファイルマッピングではなく
 CreateFile関数での排他ロックによるものです。



yout

リンク

2011/2/17(Thu) 23:53:51|NO.37167

思ったのですが、これにnote2arrayを使えば、
やはり大量のメモリあるいはディスクを使用することになるのですか?



ひらまる

リンク

2011/2/18(Fri) 01:36:25|NO.37168

>ひよこさん
たびたびすみません;
http://tokyo.cool.ne.jp/chokuto/advanced/function/CreateFile.html
を読んで理解しました。
ウィンドウズって、便利な機能がいっぱいついてるのに、それを使うのは大変なんですね。

>youtさん
はい、もちろんメモリを消費します。ディスクは消費しません。
ファイルマッピングが難しいのなら、(私も難しいです;)
私が↑で勘違いしたように、ファイルの一部だけを読み込むという方法もあります。
500Mbのファイルがどのようなものかはわかりませんが、
必要なときに必要な場所だけ読み書きすれば、メモリの代わりにCPUパワーを消費します。
つまり動作が遅くなるのですが、実装するのはとても簡単です。
noteloadの代わりにbloadを使用します。詳細についてはbloadのヘルプをご覧ください。



yout

リンク

2011/2/18(Fri) 18:03:56|NO.37174

読み込みたいファイルは素数の一覧表で、
2 3 5 7 11 13
と続いています。これを配列変数として使用したいので、
使いたい場所だけと言うのがよくわかりません。

どうしたらいいのでしょうか。



ひよこ

リンク

2011/2/18(Fri) 18:36:00|NO.37175

>youts
  素数の一覧表ですか。それは確かに配列にしないと扱いづらいですね。
  大きなファイルを読み込む方法ではありませんが、
 素数ファイルなら数値なので、バイナリにして保存したほうがよいと思います。
 そうすれば、ファイルはとても小さくなると思います。
 (もしすでになっていたら無視して結構です)
 
 二つ聞きたいことがあります。
 ・素数はいくつまでで、全部でいくつですか。(だいたいでいいです。)
 ・話をはじめに戻すようで悪いのですが、
  Windows側から報告されるエラーとはどのようなものでしょう。
 よろしくお願いします。



Jack

リンク

2011/2/19(Sat) 10:29:29|NO.37176

いちいち言葉使いやらに指摘するやつがいるけどさどんだけ中学生なの?
いちいち反応する事ないだろ^^;



ORZ

リンク

2011/2/19(Sat) 12:08:35|NO.37177

名前を変えても君が誰だかわかる人にはわかるので、顔を真っ赤にして荒らさないように。



yout

リンク

2011/2/21(Mon) 17:46:43|NO.37222

だいぶ遅れて申し訳ありません。
素数一覧は10億まで、
エラーは、「ご迷惑をおかけします。問題が発生したため、hsp3cl.exeを終了します。」
と出て、下にエラー報告をする等のボタンが出るものです。



ひよこ

リンク

2011/2/22(Tue) 18:06:46|NO.37230

#runtime "hsp3cl"
sdim Primes,507044545 notesel Primes noteload "prime10.txt" mes Primes ;ココ stop
試しに500MBのファイルを作ってこれを実行してみたところ、
おっしゃる通り、mesのところで、エラーが起きました。

いろいろいじってる途中にみつけましたが、
sdim Primes,507044545

をなくしてみてください。僕の環境ではそうしたらうまくいきました。 なぜこうなったかはわからなく、このまま使っていいとは思えませんが うまくいったことはいったのでご報告します。 もっと大きく500MBちょうどにしたり、逆に小さく「7044545」などにしてもうまくいきました。 根拠は全然ありませんが、この「507044545」あたりの数字が悪いのかもしれません。 あなたの本物の素数ファイルと、こちらのダミーの500MBちょうどのファイルは サイズも内容も全然違うのであなたの環境ではこうはいかないかもしれません。 まあ一応、sdim命令の行を無くしてみてください。



SYAM

リンク

2011/2/22(Tue) 20:02:08|NO.37235

どうも極端に大きなメモリの開放か確保のタイミングで落っこちる・・・というのは、HSPではかなり前からあったように思います。
大きなデータを扱わせたプログラムが終了時に落っこちることがあったりしますので、解放になんか問題があるのかもしれません。
このスクリプトの場合、noteloadのタイミングでメモリを再確保しようとして開放か確保に失敗してるんではないでしょか。



ひよこ

リンク

2011/2/22(Tue) 20:19:22|NO.37236

へぇ。こういう問題は前からあったんですか。
やっぱり確保か解放かどちらかで失敗が起きているのだと思います。

でも、ファイルのサイズが大きいのが問題の根本なのはほとんど間違い無く、
ファイルマッピングは都合が悪いということなので、
僕は素数ファイルをバイナリファイルにすることを推奨します。
数値だという点で扱いやすく、配列にもしやすいです。
多少バイナリへの変換に手間はかかりますが、ハードディスクのためにもなります。

是非一度ご検討を。



yout

リンク

2011/2/23(Wed) 01:16:14|NO.37247


問題が発生したため、hsp3cl.exe を終了します。 ご不便をおかけして申し訳ありません。 作業途中であった場合、その情報は失われた可能性があります。 この問題を Microsoft に報告してください。
結果はこうです。
またバイナリ化するにあたっても、こういった作業は不可欠なのではないでしょうか。



ひよこ

リンク

2011/2/23(Wed) 21:29:16|NO.37249

もちろんバイナリ化をしても確保、解放は必要ですが、サイズが小さくなりますから。

新しく、こんな方法はどうでしょう。
noteloadは読み込む場合、ファイルに合わせて変数を再確保しますが
bloadは変数に合わせてファイルを読み込みます。
もし、変数確保、解放の過程でエラーが起きていれば、
bloadを代わりに使うことによってきっと解決されます。

bloadとnoteloadは基本的にそこぐらいしか変わらないので、
多分ほかに不都合は起きません。

ちなみに僕の環境では改善されました。
成功することをお祈り致します。



yout

リンク

2011/2/28(Mon) 00:42:23|NO.37289

すみません、また落ちました。



ひよこ

リンク

2011/2/28(Mon) 19:12:08|NO.37298

あまり解決へのヒントとはなりませんが、
OllyDbgなどを使った結果、mes命令の中(?)で
なぜかメモリ00000018番地に書き込みアクセスをしているからおちるようでした。
(何度も言うようですが、「僕の環境では」ですが)


このPrimes変数に対してstrmidやpoke,peekといった動作は問題ありませんが、
strlen関数、mes、dialog命令といったことをするとおちます。
strlenは文字数を数える場合、0x00という文字コードを探しているようです。
mes,dialogもきっと同様でしょう。
そして探しているうちにアクセス禁止領域に達し、エラーが出ると思われます。

strmid,poke,peekなどは、あらかじめ処理する文字数が決まっているので
0x00を探す必要はありません。

では、これを踏まえ、こんな方法だったらどうだっ。
素数表は507044545バイトなんですよね?
ではそのつぎに0x00を書き込めば。
poke Primes, 507044545, $00

これをmes命令の前にでも入れてください。 ちなみに僕の環境では改善されました。 成功することを心よりお祈り致します。 どうか成功してくれ。



匿名希望

リンク

2011/3/1(Tue) 16:30:45|NO.37316

質問に対する答えではありませんが…

バイナリ化するにあたっても、こういった作業は不可欠なのではないでしょうか。
これはつまるところ、今使っているtxtの素数一覧をバイナリに変換する、という考え方ですよね?
HSPの仕様に振り回されながら某所の素数一覧を使うぐらいなら、自分で計算して素数リストのバイナリをつくってしまうのはいかがですか?
(そもそもあの素数一覧は、プログラムから見て扱いやすいとは言えませんし)

試し割り法で1億までの素数を計算させて見ましたが、Core i7 920 2.66GHzで5時間ほどでした。
計算量は対象範囲の1.5乗に大体比例するので、1週間もあれば10億までの素数を計算できると思います。

1億までの素数一覧のバイナリはこちらです。
http://www1.axfc.net/uploader/Si/so/100844.bin
要素数5761455の1次元配列にbloadすれば使えます。

作成するのに使ったスクリプトも提示しておきます。

#runtime "hsp3cl" #include "winmm.as" max = 100000000 ; 素数を求める範囲の最大 dim prime, int(1.2*max/logf(max)) ; 素数を代入する配列 ; int(1.2*max/logf(max)) ← 素数定理からアバウトに素数の個数を予測 prime(0) = 2, 3 ; 試し割りのルーチンで無限ループにならないように2と3だけ先に代入 num_of_prime = 2 ; 現在までの素数の個数 progress = 0 ; 進捗% timeGetTime ; あとから経過時間を細かく計るためにgettimeではなくtimeGetTimeを使用 time_start = stat ; 開始時間 log = ""+gettime(0)+"/"+strf("%02d",gettime(1))+"/"+strf("%02d",gettime(3))+"\t"+strf("%02d",gettime(4))+":"+strf("%02d",gettime(5))+":"+strf("%02d",gettime(6))+"\t"+progress+"%\t"+time_start mes log ; ログ表示 sdim log_buf, $1000 ; ログ保存用バッファ log_buf += log+"\n" ; ログを追加 repeat max-3, 4 ; cntを4から最大値まで取るループ candidate = cnt ; 素数かどうかの判定対象 repeat int(sqrt(candidate))-1, 2 ; cntを2から√(判定対象)まで取るループ ; int(sqrt(candidate)) ← √(判定対象)まで試し割りすれば十分 divisor = cnt ; 試し割りする除数 if candidate\divisor == 0 { ; 割り切れた場合 break ; 試し割り終了 } else { ; 割り切れなかった場合 if divisor == int(sqrt(candidate)) { ; √(判定対象)まで全て割り切れなかった場合 prime(num_of_prime) = candidate ; 素数を配列に代入 num_of_prime++ ; 素数の個数を更新 } } loop if int(powf(double(candidate)/max,1.5)*100) > progress { ; 1%以上進捗した場合 progress++ ; 進捗%を更新 timeGetTime log = ""+gettime(0)+"/"+strf("%02d",gettime(1))+"/"+strf("%02d",gettime(3))+"\t"+strf("%02d",gettime(4))+":"+strf("%02d",gettime(5))+":"+strf("%02d",gettime(6))+"\t"+progress+"%\t"+stat mes log log_buf += log+"\n" } wait 0 loop timeGetTime time_end = stat log = "\t"+num_of_prime+" prime numbers in 1-"+max mes log log_buf += log+"\n" ms = (time_end-time_start)\1000 sec = (time_end-time_start)/1000\60 min = (time_end-time_start)/1000/60\60 hour = (time_end-time_start)/1000/60/60 log = "\trequired "+strf("%02d",hour)+":"+strf("%02d",min)+":"+strf("%02d",sec)+"."+strf("%03d",ms) mes log log_buf += log+"\n" bsave "prime.bin", prime, num_of_prime*4 ; 素数の配列を保存 notesel log_buf notesave "prime.log" ; ログを保存 noteunsel mes "\t\tcompleted."



ひらまる

リンク

2011/3/1(Tue) 18:06:56|NO.37317

すごぉい 22Mbで済んでる!!

ところで初歩的な疑問ですが、素数のリストなど何に使うのでしょうか??

dim N, 5761455 bload "prime_100M.bin", N FontSize = 20 font msgothic, FontSize foreach N redraw 0 pos 0, 1 gmode 0, ginfo_winx, ginfo_winy gcopy 0 pos rnd( ginfo_winx + 50 ) - 50, 0 color rnd( 256 ), rnd( 256 ), rnd( 256 ) mes N( cnt ) title "" + N( cnt ) redraw 1 await 1 loop



yout

リンク

2011/3/3(Thu) 18:52:09|NO.37359

>ひよこさん

Error 20 in Line 4 (poke Primes, 507044545, $00)

となってしまいました。

その後で匿名希望さんのprime_100M.binで同じことをしましたが、
同じエラーが出て、その行を削除すると動くようになりました。



ひよこ

リンク

2011/3/3(Thu) 19:49:38|NO.37362

つまりは、バイナリにしたら動いた=解決したってことですか?

pokeの意味はなかったようですいません。



匿名希望

リンク

2011/3/3(Thu) 21:03:26|NO.37363

エラーが出る理由としては、おそらくひよこさんの考え方が近いです。
件のtxtファイルが507,044,545bytesなので、きっかり507,044,545bytesの領域を確保して読み込むと、終端コードの0x00が入る場所がなくなってしまいます。

notesel primes noteload "prime10.txt" mes primes


exist "prime10.txt" sdim primes, strsize+1 bload "prime10.txt", primes mes primes
のどちらのやり方でも問題なく表示されることを確認しました。

(今10億までの素数一覧を計算中です。予想残り時間109時間…)



ひよこ

リンク

2011/3/3(Thu) 21:47:54|NO.37364

>>匿名希望s 
 sdim命令とはもともと、その文字数分のバッファを確保するとありますから、
 内部では、それ+1分を確保していると思われます。
 しかし、今回、サイズが極端に大きいせいか、0x00が書き込まれていないようなのです。
 (strmid,peekではエラーが起きず、strlen,mesでは起きるところから考えて。)
 
 ぼくもいろいろ考え、仮定をだし、実験してみて
 どれも方法を提案しているのですが、
 僕の環境ではうまくいくのに、youtさんの環境ではうまくいかないものも多いようで。。


 話は変わりますが
 素数の計算なら、http://blog.livedoor.jp/dankogai/archives/51492290.html
 アルゴリズムはいいですよ。(HSPでなくC++で実行して確認しましたが。)
 100時間以内にこれをHSPに変換できたら、ずっと速いです。
 しかも、できるファイルの保存方法がとてもよいもので、
 サイズに無駄が全然ありません。
 (1,3,5,7,9,11…がそれぞれ素数かどうかをbooleanで表現してます。)



yout

リンク

2011/3/3(Thu) 21:51:29|NO.37365

>匿名希望さん

自分の環境のせいでしょうか、Windowsのエラー方向のあれが出ました。

>ひよこさん


#runtime "hsp3cl" exist "prime_100M.bin" dim primes,5761455 bload "prime_100M.bin", primes repeat mes primes.cnt loop stop

で、きちんと表示されました。
でも、目標は巨大テキストの読み込みでもありますので、まだ解決チェックはしません。



yout

リンク

2011/3/3(Thu) 21:55:59|NO.37366

>37364

すみません、簡単なCなら読めるのですが……



ひよこ

リンク

2011/3/3(Thu) 22:03:59|NO.37367

>>youts
 僕の環境では、匿名希望さんのスクりでは、
 上のは可能なんですが、下のはうまくいきません。
 本当に環境によって、なんですかね。

 あと、37365のスクリ、existの意味ないじゃないですか。
 次の行で、dim strsize/4ぐらいしないと駄目じゃないですか?



yout

リンク

2011/3/3(Thu) 22:19:06|NO.37368

dim strsize/4の意味がわかりません。sdimですか?

37316に使い方が書いてあったので、そうしたのですが……

existはやっぱり誤記です。



匿名希望

リンク

2011/3/3(Thu) 22:38:11|NO.37369

>>ひよこさん

sdim命令とはもともと、その文字数分のバッファを確保するとありますから、内部では、それ+1分を確保していると思われます。
これは間違いです。
マニュアルの「HSP3 文字列のひみつ(TIPS)」の、「文字列のしくみ」セクションに

ただし、256バイトのバッファを確保したとしても、255文字までしか使うことはできません。 最後に終了コード0を入れる場所が必要だからです。「sdim a,256」は、255文字+終了コード までは領域を確保するという意味になります。
とあります。

>>youtさん
巨大なtxtファイルの読み込みだけであれば、上でも何人かが挙げて下さってますが、ファイルマッピングを使うのがベストだと考えます。
素数の一覧であっても、工夫すればファイルマッピングで十分扱えます。



ひよこ

リンク

2011/3/3(Thu) 22:43:42|NO.37370

>>youtさん
 いえ。どちらでもよいのです。
 existは誤記だったということで別にいいのですが、一応解説させていただきます。
 
 先にいっときます。電卓で計算してもらうとわかりますが、
 strsize/4と5761455は等しいです。
 ただ、existを実行しているのに何にも使ってないので、生かそうとしただけです。
 
 prime_100M.binはバイナリファイルで、4byteで一数値を書き込んでいるので、
 [素数の個数]*4(byte)がファイル全体のバイト数となります。
 つまり、[ファイルサイズ(byte)]/4(byte)==[素数の個数] となるわけです。
 existはファイルのバイト数をstrsizeにいれるわけですから、
 strsize/4で素数の個数、すなわち確保すべきPrimeの要素数なわけです。

>>匿名希望さん
 そうだったんですか。
 sdimのHSP Document Libraryみたら「5000文字分の〜」と書いてあったので、
 てっきり+1確保してるんだと思いました。
 よくよく考えれば、確かに「5000文字ぶんのメモリをあらかじめ確保」には
 0x00もはいっているともとれますね。
 自分のミスを他人のミスのように言ってしまいすいませんでした。



匿名希望

リンク

2011/3/4(Fri) 00:45:24|NO.37373

>>ひよこさん
お気になさらず。
NO.37364を見てエラトステネスのふるいを思い出したので実装してみたところ、10億までの素数が11分でリストアップできました。
ひよこさんのおかげです。

ただ、boolean型に関してはHSPで扱いにくいので、bit単位ではなくbyte単位で処理しています。
途中の段階でそれぞれの数が素数かどうかのリストもできているのですが、上述の理由により1GBにも達してしまいました。
(奇数に絞り込むだけで半分までは縮小できますが…)

以下にソースを提示しておきます

#runtime "hsp3cl" #include "winmm.as" max = 1000000000 sdim primes, max+1 mes ""+gettime(0)+"/"+strf("%02d",gettime(1))+"/"+strf("%02d",gettime(3))+" "+strf("%02d",gettime(4))+":"+strf("%02d",gettime(5))+":"+strf("%02d",gettime(6))+"\tinitialization started." timeGetTime time_start = stat repeat max-1, 2 poke primes, cnt, 1 await 0 loop mes ""+gettime(0)+"/"+strf("%02d",gettime(1))+"/"+strf("%02d",gettime(3))+" "+strf("%02d",gettime(4))+":"+strf("%02d",gettime(5))+":"+strf("%02d",gettime(6))+"\tcalculation started." repeat int(sqrt(max)), 2 divisor = cnt if peek(primes,divisor) { repeat max/divisor-1, 2 poke primes, divisor*cnt, 0 loop } await 0 loop mes ""+gettime(0)+"/"+strf("%02d",gettime(1))+"/"+strf("%02d",gettime(3))+" "+strf("%02d",gettime(4))+":"+strf("%02d",gettime(5))+":"+strf("%02d",gettime(6))+"\tlisting started." dim prime, int(1.2*max/logf(max)) repeat max-1, 2 if peek(primes,cnt) { prime(num_of_prime) = cnt num_of_prime++ } await 0 loop timeGetTime time_end = stat required_ms = time_end-time_start required_sec = required_ms/1000 required_min = required_sec/60 required_hour = required_min/60 required_min \= 60 required_sec \= 60 required_ms \= 1000 mes ""+gettime(0)+"/"+strf("%02d",gettime(1))+"/"+strf("%02d",gettime(3))+" "+strf("%02d",gettime(4))+":"+strf("%02d",gettime(5))+":"+strf("%02d",gettime(6))+"\tcompleted." bsave "prime_byte.bin", primes bsave "prime_int.bin", prime, num_of_prime*4 mes ""+num_of_prime+" prime numbers in 1-"+max mes "required "+strf("%02d",required_hour)+":"+strf("%02d",required_min)+":"+strf("%02d",required_sec)+"."+strf("%03d",required_ms)

sdimで(max+1)bytes確保した変数に"prime_byte.bin"を読み込み、peek(読み込んだ変数名,素数かどうか判定したい数)とやると、素数なら1/合成数なら0が返ります。
"prime_int.bin"は、NO.37316でUPしたものと同じ形式で、4bytes毎にint型で素数が記録されています。
NO.37370でひよこさんが解説して下さっている様に、existの後dimで要素数(strsize/4)の1次元配列を確保して読み込めば使えます。



yout

リンク

2011/3/5(Sat) 17:29:20|NO.37412

37373を使って、ファイルを作ってそれをbloadしようかと思います。
ですが、37373を3時間ほど動かしても、終わりません。



匿名希望

リンク

2011/3/5(Sat) 21:11:36|NO.37426

"prime_byte.bin"と"prime_int.bin"の詰め合わせcabファイルです
http://www1.axfc.net/uploader/P/so/86980

ちなみに


ですが、37373を3時間ほど動かしても、終わりません。

では、何がどうなっているのかわかりません。
・CPU/メモリ容量
・表示はどこで止まっているのか
を書いてもらえれば、原因や対処法がわかるかもしれません。



ひよこ

リンク

2011/3/5(Sat) 21:15:31|NO.37428

>>匿名希望さん
 メモリ量については、このスレッドの上のほう、37152にかいてありますよ



yout

リンク

2011/3/6(Sun) 00:44:17|NO.37435

OS
WinXp Service Pack 3
CPU
Pentium 4 320GHz 319GHz
RAM
物理 0.99GB
コミットチャージ 2.44GB

環境上記のとおりです。
停止時の表示はcalculation started.です。

また、sdim単体の時間も合わせて計測しましたが、40秒ほどかかっています。



匿名希望

リンク

2011/3/6(Sun) 04:13:09|NO.37442

NO.37152は見落としていました。
すみません。

一言で言うとメモリ不足です。
1GB近くのメモリ領域を確保しようとしているのにRAMが1GBしかないので、HDDから1GBのメモリ領域を確保(ページング)していると思われます。
HDDの読み書き速度はRAMと比較にならないほど遅いので、それがパフォーマンスの低下につながっています。
結論としては、NO.37373で提示したスクリプトをそちらの環境で動かすのは諦めていただいた方が良いと思います。

ところでNO.37426でUPしたファイル(の内"prime_int[_1G].bin")は利用できましたでしょうか?
(上述の理由により、"prime_byte[_1G].bin"を利用するのは避けていただいた方が良いと思います。)



yout

リンク

2011/3/7(Mon) 17:11:43|NO.37471

37426のprime_int_1G.binは使えました。ありがとうございます。

ですが、HSPで1bit単位のメモリ管理はできないのでしょうか。
それができれば、速度がもっと上がると思うのですが……



匿名希望

リンク

2011/3/7(Mon) 18:11:41|NO.37473

利用できたようでよかったです。


ですが、HSPで1bit単位のメモリ管理はできないのでしょうか。 それができれば、速度がもっと上がると思うのですが……

実はNO.37373のスクリプトの素数判定部分をbit単位で実装してみたのですが、処理時間が3倍以上にもなってしまいました。
(奇数のみに絞り込んでの判定でも、2倍近くかかる計算になります。)
メモリ読み書きの命令は、最小でもpeekとpokeの1byte単位なので、無駄なビット演算が増えてしまうのが原因です。
消費メモリを1/8に節約できるのは大きいですが、高速処理には向きません。
(もちろん、メモリの少ない環境ではページングが発生しない分、速度の上昇が見込まれますが。)



yout

リンク

2011/3/7(Mon) 18:25:42|NO.37474

>37473
メモリの読み書き(特に読み)の最小単位をAPIあるいはDLLや機械語でbyteにできませんか?



ひよこ

リンク

2011/3/7(Mon) 18:56:28|NO.37476

もうバイナリにして、配列を扱う必要もなくなったので、
ファイルマッピングのほう、検討していただいたほうが早いかと。



ひよこ

リンク

2011/3/7(Mon) 19:13:31|NO.37478

>>youtさん
 byte単位なら、peek,pokeでいいんじゃないんですか?



yout

リンク

2011/3/8(Tue) 00:48:54|NO.37489

>37476
ファイルマッピングなら巨大なファイルであっても
読み込みだけなら何とかなるのでしょうか。
速度が心配です。

>37478

p2=0〜 : バッファのインデックス(Byte単位) 解説 変数に保存されたデータメモリ上の任意の場所にある1バイト(8bit)の内容を数値として返します。 関数の戻り値は、0〜255までの整数値になります。



ひよこ

リンク

2011/3/8(Tue) 18:23:15|NO.37497

>>youtさん

>>37476
>ファイルマッピングなら巨大なファイルであっても
>読み込みだけなら何とかなるのでしょうか。
>速度が心配です。
 読み込みも書き込みも可能です。
 速度は、これ以上速い方法はないだろう、というぐらい速いです。
 500MBあっても、1秒くらいで動きます。(僕のでは)

>>37478
>p2=0〜 : バッファのインデックス(Byte単位)
>解説
>変数に保存されたデータメモリ上の任意の場所にある1バイト(8bit)の内容を数値として返します。
>関数の戻り値は、0〜255までの整数値になります。
だからなんですか?
ちゃんと
「メモリの読み書き(特に読み)の最小単位を"基本命令だけ"でbyteにでき」てるじゃないですか。



zakki

リンク

2011/3/8(Tue) 21:46:40|NO.37505

OpenHSPのほうでテストしてみました。
noteloadとmesで落ちるのは単純にメモリ不足ではないでしょうか。

OpenHSPの実装を見る限りmesで文字列を出力するには一時的に文字列の3倍以上のメモリが必要です。
32bitプログラムで利用可能なメモリは普通2GB程度なので500MBの3倍となると
他での消費やメモリ管理でのオーバーヘッドもあわせるとかなり厳しいかと思います。



yout

リンク

2011/3/9(Wed) 04:39:18|NO.37507

>37497

先ほどのメモリのページングのときにだいぶ遅くなると聞いたのですが、
その辺は大丈夫なのですね。

それから、質問が悪かったです。
「HSPで変数に保存されたデータメモリ上の任意の場所にある1byteの内容を数値として返す
方法はありませんか?」



匿名希望

リンク

2011/3/9(Wed) 06:54:34|NO.37509

> HSPで変数に保存されたデータメモリ上の任意の場所にある1byteの内容を数値として返す
のと
> 変数に保存されたデータメモリ上の任意の場所にある1バイト(8bit)の内容を数値として返します。
の違いがわかりません。
1byteならpeekとpokeでインデックス(場所)を指定することで可能です。
1bitの間違いでしょうか?

> メモリの読み書き(特に読み)の最小単位をAPIあるいはDLLや機械語でbyteにできませんか?
bitだと仮定した場合、おそらく不可能です。
Win32APIどころかx86アーキテクチャにも、メモリ上の特定ビットだけを読み取(書き換え)る命令は(私の知る限り)ありません。
読み取り:1byte読み出し→ビットマスク
書き換え:1byte読み出し→ビット演算→元のアドレスに書き込み
といった手順を踏むことになります。

他言語に詳しくないため、NO.37373で紛らわしい書き方をしてしまいましたが、そのせいで勘違いさせてしまったとしたら済みません。
大抵の言語では、bool型のサイズは1byteないし(32bit処理系の場合)4byteになっているようです。

32bit処理系の環境では、32bit(4byte)単位のメモリアクセスが一番効率が良いと言われています。
1bit単位の読み書きアクセスを実装しても、余計なオーバーヘッドが生じる分処理効率は上がらないでしょう。
(繰り返しますが、物理メモリの少ない環境では速度向上が見込まれるかもしれません。)

あと横レスですが
> 先ほどのメモリのページングのときにだいぶ遅くなると聞いたのですが、その辺は大丈夫なのですね。
ページングとファイルマッピングは仕組みからして全然違います。
少しアバウトな言い方をすると、必要なメモリ領域をHDD領域に依存するのがページングで、最小限の変更点をメモリ上に置いてキャッシュしながらHDDにアクセスするのがファイルマッピングです。

必要な関数は既にひよこさんが答えてくださっているので、興味があるなら実際に試してみるのが一番だと思います。
ここで処理速度について質問しても、実際の処理については何も身につきませんので。



yout

リンク

2011/3/9(Wed) 15:20:59|NO.37514

>37509
1bitです。すみません。

メモリマップトファイルを実装してみましたが、動きません。
最初のfailed.が表示されるようです。


#runtime "hsp3cl" #include "kernel32.as" name = "prime_byte_1G.bin" exist name textsize =strsize onexit *OnAppExit CreateFile name,8,0,0,3,1,0 hfile =stat CreateFileMapping hfile,0,2,0,0,0 hmapobj =stat if hmapobj =0{ mes "failed." stop} GetLastError if (stat =183){ mes "failed." stop} MapViewOfFile hmapobj,4,0,0,0 lpdata =stat dupptr isprime,lpdata,textsize,2 mes peek(isprime,53) stop *OnAppExit UnmapViewOfFile lpdata if hmapobj{ CloseHandle hmapobj } end



ひよこ

リンク

2011/3/9(Wed) 18:28:59|NO.37517

CreateFileへの第二引数が不正です。
GENERIC_READは$80000000,GENERIC_WRITEは$40000000です。



yout

リンク

2011/3/10(Thu) 02:56:55|NO.37524


#runtime "hsp3cl" #include "kernel32.as" name = "prime_byte_1G.bin" exist name textsize =strsize onexit *OnAppExit CreateFile name,0x80000000,0,0,3,1,0 hfile =stat CreateFileMapping hfile,0,2,0,0,0 hmapobj =stat if hmapobj =0{ mes "failed." stop} GetLastError if (stat =183){ mes "failed." stop} MapViewOfFile hmapobj,4,0,0,0 lpdata =stat dupptr isprime,lpdata,textsize,2 mes peek(isprime,99999989) stop *OnAppExit UnmapViewOfFile lpdata if hmapobj{ CloseHandle hmapobj } end

これできちんと動きました。
皆さんありがとうございます。

また最初の質問も37505で解説されています。
ありがとうございました。



ONION software Copyright 1997-2023(c) All rights reserved.