トピック
ナルミンチョ naru_starfy28

COPY命令でコピー元とコピー先が同じ場合

配列Aは [0,1,2,3,4,5,6,7,8,9] からCOPY命令で、 [0,0,1,2,3,4,5,6,7,8] に変換したかったが、 実行してみたら [0,0,1,2,3,4,5,6,7,7] になってしまった。バグかな?
3そうだね
プレイ済み
返信[1]
親投稿
ナルミンチョ naru_starfy28
POPとUNSHIFTを使うか、 いったん別の配列にコピーすれば回避できます。 逆方向のコピー [0,1,2,3,4,5,6,7,8,9]から [1,2,3,4,5,6,7,8,9,9]にするのは 問題なくCOPY命令で、できます。
0そうだね
プレイ済み
返信[2]
親投稿
ナルミンチョ naru_starfy28
Aを文字列の配列A$にして実行すると、 ["0","1","2","3","4","5","6","7","8","9"]が、 ["0","0","0","0","0","0","0","0","0","0"]になります。 これは、文字列が参照型の面もあるので、 A$[1]=A$[0] A$[2]=A$[1] … という感じなり、全て0になる理由がわかります。
2そうだね
プレイ済み
返信[3]
親投稿
ナルミンチョ naru_starfy28
2つずらす場合 [0,1,2,3,4,5,6,7,8,9]を [0,1,0,1,2,3,4,5,6,7]にしたかったが、実行してみると [0,1,0,1,2,3,2,3,6,7] になってしまう。
0そうだね
プレイ済み
返信[4]
親投稿
ナルミンチョ naru_starfy28
3ずらし [0,1,2,0,1,2,3,1,2,3] 4ずらし [0,1,2,3,0,1,2,3,0,1] になってしまう。 5ずらしは問題なく [0,1,2,3,4,0,1,2,3,4]になる。
0そうだね
プレイ済み
返信[5]
親投稿
ナルミンチョ naru_starfy28
文字列配列のときの挙動はわかるが、 数値配列のときはよくわからない。 基本的には、POPとUNSHIFTを使えば、良さそう。 問題のない逆向きなら、COPYの方が若干速いので、速さを必要とするならばCOPYとPOP UNSHIFTを使い分ければいいのか。
0そうだね
プレイ済み
返信[6]
親投稿
MIKI ifconfig
初版から存在する由緒正しいバグみたいですよ。 https://miiverse.nintendo.net/posts/AYIHAAAEAAArVRTsLFZ1rg
1そうだね
プレイ済み
返信[7]
親投稿
ナルミンチョ naru_starfy28
MIKIさん そうだったんですか。 プチコンは配列周りが不安定な感じがします。アクセスも遅いし。今後のアップデートで改善されることを願います。
0そうだね
プレイ済み
返信[8]
親投稿
ツララ LongIceSword
はぇ〜、分かり辛いからバグって決めつけて公式の対応待ちにして放り投げないで、しっかりと不具合の回避方法も検証されてて完璧ですね。 逆に意図通りの挙動しないのを利用して便利な活用法考えるの、おちゃめさんとかならやってくれそう。
0そうだね
プレイ済み
返信[9]
親投稿
myu314 myu314
恐らく高速化のため256bytesずつコピーだと思うので、バグと言ってしまうのはちょっとかわいそうかなと。 (実数なら4つずつコピーするって考えれば挙動は理解できると思います) マニュアルにはきちんと書いておくべきだと思いますけども。 デフォルトでmemmoveな挙動にしてしまうと大分パフォーマンスに影響でますし…。 文字列の方はアライメントの影響でまとめてコピーできなくて挙動が変わったんでしょうね。
0そうだね
プレイ済み
返信[10]
親投稿
myu314 myu314
ちなみに最初の例だと[0,0,1,2,3,4,5,6,7,7]ではなく [0,0,1,2,3,3,5,6,7,7]になってたかと。 [0123]456789 => 0[0123]56789 0012[3567]89 => 00123[3567]9 00123356[7]9 => 001233567[7] って感じで。
1そうだね
プレイ済み
返信[11]
親投稿
myu314 myu314
あ、256bytesじゃない。256bits=32bytesの間違いです。お恥ずかしい。
0そうだね
プレイ済み
返信[12]
親投稿
ナルミンチョ naru_starfy28
ツララさん 活用法考えてみました。 ディスプレイを虫眼鏡でみた感じの模様がランダムに描画されます。
0そうだね
プレイ済み
返信[13]
親投稿
ナルミンチョ naru_starfy28
繰り返しの部分をこうすれば、8ドット以上も繰り返せるのか。こっちの方がきれい。
0そうだね
プレイ済み
返信[14]
親投稿
ナルミンチョ naru_starfy28
myu314さん 確かに最初の結果間違ってました。 [0,0,1,2,3,3,5,6,7,7]になります。 (こっちの方が恥ずかしい) わかりました。ありがとうございます。そういうことだったんですね。 確かに32byteずつコピーされていますね。整数型だと4byteなので、8ずつコピーされる。 プチコンには明記されていないことが多いですね。
0そうだね
プレイ済み
返信[15]
親投稿
MIKI ifconfig
myu314さん情報ありがとうございます。256bitというのは気づきませんでした。 armは詳しくないですが、256bit単位だと速度的に何かいいことあるのですか? 8bit境界でも256bitアクセスできるのも不思議な感じ。 copy a,1,a,0,n 命令の内部処理は 1 引数の個数で分岐(これはもしかしたらコンパイル時に決定してるかも) 2 引数1と引数3が同じ型の配列変数であることを確認 3 その型(文字列か数値か)によって分岐 4 コピー元アドレスとコピー先アドレスを決定 5 floor(総bit数/256)回コピー(256bit単位) 6 (総bit数 mod 256)/8回コピー(8bit単位) ここで 4 あたりで重なり判定をすればいいだけと思いますが、速度に対するインパクトはそんなに大きいですか?
0そうだね
プレイ済み
返信[16]
親投稿
myu314 myu314
僕もARM全然知らないんですけども、ベクトル化されたらそんなものかなーぐらいの気持ちで前のコメントしました。 32bit境界が期待できない文字列の場合で処理が違ってるようなので、まあ最適化による仕様だろうなと。 速度のインパクトですけど、どれくらい差があるかはわかりませんが、プチコンから使うことを考えるとまず無いでしょうね。 参考程度にnewlibっていう組み込み向けのライブラリのソース眺めてみましたが、memmoveとmemcpyの差は重複チェックして場合によっては逆からコピーに変えてるだけでした。 同じことをプチコン側もやってくれれば、恐らくみんな幸せな気がします。 前のコメントの「パフォーマンスに影響でますし」は迂闊でした、撤回させていただきます:)
0そうだね
プレイ済み
返信[17]
親投稿
MIKI ifconfig
myu314さん よほどのことがないと C で書いちゃうので、CPU が何か便利な機能持ってたとしてもいちいち気づかないですよね。 newlib は知りませんが、memmove と memcpy が異なるというのは誠実だなと思いました。 私だったら memmove 書いて、 memcpy は memmove 呼び出すだけにしちゃう(逆に遅いww)。
0そうだね
プレイ済み
返信[18]
親投稿
リファレンスに書き忘れてるだけで、実はsrcとdst一緒にすると正しく動きませんな仕様な感じするなぁ。 32bytes境界はsmile basic設計上な感じもするけどどうなのかなー 速度よりbuffer overrun対策な感じもするし。 参照先同じにしてもとりあえず落ちないし、いじるといろいろ周りが大変そうだからそのまま放置されてそうな感じする。
0そうだね
プレイ済み