たぶん役に立たない話


2010/07/11 Windows 2008 Server で動かしてみる

Windowsの64ビット環境では32ビットアプリも動くことになっている。 試しに64ビット専用のWindows 2008 Server R2 (評価版)の環境を作って うにωを動かしてみたら…あらら。あっさり落ちちゃった。

最初はVFWの互換性みたいなのを考えたが、すぐに原因が うにωの中にあることが分かった。Xbyakで実行時に生成したコードのメモリ領域に 実行権限を付加するところが一箇所漏れていた。

WindowsXP SP2 以降にはデータ実行防止(DEP:Data Execute Prevention)というセキュリティ機能がある。 これが有効だとデータ上に展開したコードはプログラム内で実行権限を設定しない限り動かない。 このDEP、OSの系統によって初期設定が違う。クライアント系(XP,Vista,7)だと「重要なWindowsのプログラムだけ有効」、 サーバ系(2003,2008)だと「例外を除く全てで有効」。

うにωはWindowsにとって重要ではないので、クライアント系OSを初期設定で使っていると、動いてしまい気付かなかった。 そのへん修正したらあっさり動いた。難しいかなーと考えていたマルチプロセスエンコード機能も問題なし。 まあ、この程度で動かないようだと64ビットOSが売れないのでMSもちゃんと考えているんだろう。

うにωの手の込んだ仕様に1パス目の画像をとっておいて2パス目で読み返す、というのがある。 こういうことをするのはコーデックのインタフェース仕様を満足しつつ、フレームリオーダやら未来方向予測やらを 実現するためなのだが、それには巨大な中間ファイルが必要になる。

中間ファイルは画像なので圧縮が効く。 Ver1.100以前では(作るのが面倒だったので)他で使っている算術符号を使い回しており、結構な負荷になっていた。 Ver1.110ではこれを専用のハフマン符号に置き換えた。算術符号との速度差は優に100倍を超え、エンコード全体の速度もそれなりに速くなった。 副作用で中間ファイルが若干大きくなるが現代のディスク容量なら平気だろう。 もちろん中間ファイルの話なので最終結果の動画には影響が無い。

試しに圧縮しない版も作ってみた。速度は ハフマン符号>算術符号≒圧縮なし、の順になった。 算術符号と圧縮なしで速度差が出ないのは作者のHDDがそれほど速くなく、HDDのアクセス時間と符号器の速度が同レベルだから。 高速SSDだと圧縮なし版がずっと速くなると思う。 もっともそれ以上にハフマン符号は爆速だし、何よりSSDを中間ファイルに使ったりはしないだろうから現状では妥当な解だと思う。

Ver1.110でいきなりDLLのサイズが2倍以上になった。これはコンパイラを変えたときに影響が出ないように 色々配慮したのと、アセンブラ部分をXbyakに置き換えた上で32/64ビット共通にしているため。 これらはまだまだ途中。そのうちなんとかなるだろう。


2010/11/8 うにω64ビット版

ようやく64ビット版が動いた。Cで書いている部分は注意すれば32/64ビット共通のコードにできるが、さすがにアセンブラ部分は 完全共通は無理。それでも95%程度は共通コードなので、今後改修するときの手間はそんなに大きくない。

32ビット版と64ビット版でDLL名を変えているのでシステム上に共存できる。たとえばAviUtl(32ビット)からはこんな風に見える。

一方、VirtualDub(64ビット)からはこんな感じ。

再生環境は特に考えなくて良い。32ビット版、64ビット版のどちらで伸張してもちゃんと動く。

肝心の処理速度だが面白い結果が出た。 いまのところサブマシン(CPUはCore2)でテストしているのだが、明らかに32ビットの方が速い。 巷で言われているように、Core2の64ビット対応ってやっつけ仕事だったんだなーって気がする。 もうすぐメインマシン(Core i7)の方も64ビットOSにするので、そうしたら再度測定する予定。 (それで64ビットの方が遅かったらどうしよう?)

公開する前に1月ほど自分で使って問題の無いことを確認している。そういったわけで公開は12月の予定。


2010/11/22 うにω64ビット版(その2)

Core2で遅くて悔しかったので少々64ビット最適化を施した。 増えたレジスタが効きそうなところ、動き検索や直交変換に64ビット専用モジュールを用意した。 結果はこんな感じ。VirtualDubの影響が出ないよう、未圧縮の映像をフィルタなしで使っている。ターボモードなどはoffだ。

32Bit(WOW64) 64Bit
Core 2 595秒 595秒
Core i7 226秒 217秒

Core2でイーブンまで持ってこれた。ただ全く同じという訳ではなく映像によって若干変動がある。まあ平均すれば同程度と言えそう。 一方、i7では確実に64ビット版が速い。巷では64ビットの方が遅いアプリもあるわけで、それに比べれば良いレベルだと思う。

ちなみにWindowsXP(32ビット)とWOW64では誤差レベルの違いしか出ない。 ほとんどシステムコールを使わずに計算だけ繰り返しているプログラムだから、当然だ。

面白い実装にしてみた。うにωはマルチプロセスモードといって、 エンコードを複数のプロセスに振り分けてCPUを限界まで使い切るしくみを持っている。 このとき生成するスレーブプロセス、WOW64の環境では親のプロセスに関わらず64ビットになる。 たとえばAviUtl(32ビット)から使うとこんな感じ。 32ビットのAviUtlから呼ばれた32ビットのうにωが64ビットのスレーブプロセスを作って、 そちらに仕事のほとんどを押し付けている格好になる。

WindowsXP(32ビット)だとこうなる。これは今と同じ。

・・・少しぐらい良いことがないとわざわざ64ビットにする甲斐がない。 XPで使っていたアナログのキャプチャカードは使えなくなった。 映れば良いという用途なら軽くて便利だったのだが。 今の地デジキャプチャカードは金を払う価値がないし、 今更アナログも何だからIOデータのチューナユニットを買った。 まあPCなしでもテレビが映ると思えばよい。

上とは関係ない話だが、変愚蛮怒にハマっている。なかなかに面白い。先日はブル・ゲイツが出てきた。
それ「ウィンドウズ2000を買うのだ。ファイルシステムが素晴らしいぞ!」
「ブル・ゲイツ」は請求書をよこした。しかしすばやく財布を守った。
「ブル・ゲイツ」は請求書をよこした。しかしあわててザックを取り返した!

結局ブル・ゲイツに殺された。何なんだこれは


2011/06/18 mdadm と戯れる

CPUは壊れても買い直せばいいだけなのだが、HDDはそうはいかない。 消耗品と割り切って元気に動いているうちに交換するに限る。 もっともそれは間違いなく交換できたらの話だが…

使用中の奴は500GBx4のRAID5で1.5TB。このうち1TBが埋まっている。これを2TBx4の新ドライブに交換する。 ちなみに3年前に買った500GBのドライブは12,000\位だった。今回買った2TBのドライブは8,000\弱。 どうみてもデータ消費率よりビット単価の下落率が大きい。損したような気もするが、こればっかりはしょうがない。

マザーのSATAポートが4つしかないので一旦別マシンを踏み台にして構築後、データ移行する。手順はこんな感じ。

  1. 踏み台マシンにUSBメモリとHDD4台だけ繋いで、USBメモリにUbuntuをインストールする。
  2. RAID5を構築したら、現用のRAIDマシンから踏み台マシンにLAN経由でデータコピー。
  3. 踏み台マシンからUSBメモリとHDDを取り出し、RAIDマシンに差し替えて完了。

最近のLinux系のOSはUSBメモリに入れて持ち運べる。こういうときに便利だ。

■その1 構築

特に考えもせず、Ubuntu 10.10 Desktop 64Bit版を使う。 RAID専用機なので64ビットでの互換性云々は気にしない。 64Bit版だと日本語Remixはないが、必要なら後からパッケージを追加すれば良いし、 そもそも日本語である必要性も薄い。

Ubuntuを使って思うのだが、GUIでRAID構築ができそうなフリして、 実のところはmdadmを追加しなければ動かない、っていう類のチグハグなところがある。 慣れれば平気なんだが、初めて使う人にとってはもの凄く高いハードルだと思う。 このあたり何とかならないと普通の人はいつまでも蚊帳の外って感じがする。

RAIDは首尾よく構築。合計6TBもあるせいか、ビルドに9時間もかかった。 映像関連の大きいファイルが大半なのでファイルシステムは xfs を選択。 この辺、実際のところメンテされているファイルシステムなら何でも良いと思う。

■その2 データコピー

データコピー開始。さすが1TB、終了まで12時間かかった。 終了後に気になったんだが、本当に間違いなくコピーされたんかいな?  というのも、HDDには故障していなくてもエラーレートというのが存在する。 たとえばHGSTのこちらにある データシート上では Error rate = 1 in 10^15Bit とされている。1TB≒10^13Bitなのだから、運悪く当たってしまうレベルだ。 具体的な値はわからないが、LANのエラーレートってのもあるはずだ。

で、どうするか? コピーの信頼性を疑っているのだからネットワーク越しで比較しては意味がない。 比較する度に違うってこともあり得るし、検証に半日もかけるのは何か気が乗らない。 結局、踏み台マシンと現用マシンの両方でこんなコマンドを動かした。

for FILE in `find /RAID -type f | sort`; do md5sum "$FILE" >> hash.txt; done

/RAIDがマウントポイント。それ以下の全ファイルをスキャンしてmd5ハッシュを求め、hash.txtに記録する。 あとは両方のhash.txtを比較すれば(ハッシュレベルだが)同一性を確認できる。 結果が出るまで1時間ぐらいかかった。果たして結果は…全ファイル一致。 100円ショップで買ったLANケーブルでも問題ないってことなんだろう。

このとき、何気なくhash.txtを取っておいた。これが後になって凄く重要なものになる。

■その3 RAID解体

500GのHDDが4台余った。あまり信頼性が要らない箇所に再利用する、 ということで最近導入したCore i7 2600K マシンの一時データ保管庫にした。 3年前のものとはいえ、使うときだけしか電源を入れていない。 S.M.A.R.T.のデータを見たら使用時間が300時間を切っていた。まあそれなりに動いてくれることだろう。

今更だが、ここで解体してしまったのは、まずかった。

■その4 RAID崩壊

6TBもあるのだ。この際、色んな物を放り込んでおこう。どうせ次回更改時にも余るのだから…
そう思って手当たり次第コピーしていたのだが、ふとある瞬間「ネットワークドライブが切断されました」のメッセージが。 えっ?と思ってUbuntu側で確認するとmdデバイスが見えない。

唸りながら何気に踏み台マシンのチップセットを触ったら「じゅっ」と音がした。すごい温度だ。 そういえばHDDを入れるときに排気ファンの配線がじゃまだったので外したまま、 ビルドとコピーでずっとつけっぱなしにしていた。 画面は表示されていたし、HDDを触ってもそれほど熱くない。やっぱりチップセットの熱暴走っぽい。

一旦電源を切ってファンを繋いで祈りながら再起動。やっぱりmdデバイスが見えない。 アミバ様っぽく「ん!? まちがったかな・・・」などどいいながら、スーパーブロックを確認してみる。 (ここは後学のためのメモしておいた)

sudo mdadm --examine /dev/sda1
/dev/sda1:
          Magic : a92b4efc
        Version : 1.2
    Feature Map : 0x1
     Array UUID : bf2c60f6:17268f0e:540f68af:22e92873
           Name : :RAID6T
  Creation Time : Sat Apr  2 20:56:11 2011
     Raid Level : raid5
   Raid Devices : 4

 Avail Dev Size : 3907028829 (1863.02 GiB 2000.40 GB)
     Array Size : 11721083904 (5589.05 GiB 6001.19 GB)
  Used Dev Size : 3907027968 (1863.02 GiB 2000.40 GB)
    Data Offset : 272 sectors
   Super Offset : 8 sectors
          State : active
    Device UUID : d60b1560:2edd7a43:22812f1c:2448bf2f

Internal Bitmap : 8 sectors from superblock
    Update Time : Sat Apr  9 22:35:30 2011
       Checksum : 76b79900 - correct
         Events : 4974

         Layout : left-symmetric
     Chunk Size : 512K

   Device Role : Active device 3
   Array State : AAAA ('A' == active, '.' == missing)
sudo mdadm --examine /dev/sdb1
/dev/sdb1:
          Magic : a92b4efc
        Version : 1.2
    Feature Map : 0x1
     Array UUID : bf2c60f6:17268f0e:540f68af:22e92873
           Name : :RAID6T
  Creation Time : Sat Apr  2 20:56:11 2011
     Raid Level : raid5
   Raid Devices : 4

 Avail Dev Size : 3907028829 (1863.02 GiB 2000.40 GB)
     Array Size : 11721083904 (5589.05 GiB 6001.19 GB)
  Used Dev Size : 3907027968 (1863.02 GiB 2000.40 GB)
    Data Offset : 272 sectors
   Super Offset : 8 sectors
          State : active
    Device UUID : 6d07a2f5:8029b1d4:173ba2aa:4cdf68fe

Internal Bitmap : 8 sectors from superblock
    Update Time : Sat Apr  9 22:35:30 2011
       Checksum : fa973204 - correct
         Events : 4974

         Layout : left-symmetric
     Chunk Size : 512K

   Device Role : Active device 0
   Array State : AAAA ('A' == active, '.' == missing)
sudo mdadm --examine /dev/sdc1
/dev/sdc1:
          Magic : a92b4efc
        Version : 1.2
    Feature Map : 0x1
     Array UUID : bf2c60f6:17268f0e:540f68af:22e92873
           Name : :RAID6T
  Creation Time : Sat Apr  2 20:56:11 2011
     Raid Level : raid5
   Raid Devices : 4

 Avail Dev Size : 3907028829 (1863.02 GiB 2000.40 GB)
     Array Size : 11721083904 (5589.05 GiB 6001.19 GB)
  Used Dev Size : 3907027968 (1863.02 GiB 2000.40 GB)
    Data Offset : 272 sectors
   Super Offset : 8 sectors
          State : clean
    Device UUID : 7128a6c7:c60684ff:7ee553f0:3e4b3a2d

Internal Bitmap : 8 sectors from superblock
    Update Time : Sat Apr  9 22:39:50 2011
       Checksum : 6bf146a8 - correct
         Events : 4979

         Layout : left-symmetric
     Chunk Size : 512K

   Device Role : Active device 1
   Array State : .AA. ('A' == active, '.' == missing)
sudo mdadm --examine /dev/sdd1
/dev/sdd1:
          Magic : a92b4efc
        Version : 1.2
    Feature Map : 0x1
     Array UUID : bf2c60f6:17268f0e:540f68af:22e92873
           Name : :RAID6T
  Creation Time : Sat Apr  2 20:56:11 2011
     Raid Level : raid5
   Raid Devices : 4

 Avail Dev Size : 3907028829 (1863.02 GiB 2000.40 GB)
     Array Size : 11721083904 (5589.05 GiB 6001.19 GB)
  Used Dev Size : 3907027968 (1863.02 GiB 2000.40 GB)
    Data Offset : 272 sectors
   Super Offset : 8 sectors
          State : clean
    Device UUID : 57de2fc9:ee47bfd5:fdbbe8b1:0a7b9243

Internal Bitmap : 8 sectors from superblock
    Update Time : Sat Apr  9 22:39:50 2011
       Checksum : 1ba34402 - correct
         Events : 4979

         Layout : left-symmetric
     Chunk Size : 512K

   Device Role : Active device 2
   Array State : .AA. ('A' == active, '.' == missing)

mdadmのことはあまり詳しくはないのだが、それでも表示内容を見ていると何となく何が起きたか分かってくる。 どうやら書き込み途中に /dev/sda1 と /dev/sdb1 が同時に見えなくなったっぽい。 これら2つのEventsが4974で止まっている一方、残り2つのEventsが4979まで進んでいる。 2デバイスが無くなったのだからRAID5として機能できなくなって当然だ。で、どうするよ・・・

■その5 RAID再構築

S.M.A.R.T.のデータを確認してみると一応HDD単体としてはエラーが無いようだ。やっぱりRAIDのレベルで崩壊している。 色々ネットで情報を漁っているうちに、強制的に再構築を指示することができるらしいとわかった。コマンドは以下。

sudo mdadm --assemble /dev/md0 -u bf2c60f6:17268f0e:540f68af:22e92873 --force --run

-u の後ろの bf2c・・・はアレイのUUID。スーパーブロックのArray UUIDのところに示されている奴だ。 後ろの --force が強制再構築指示。もっとも再構築できるかどうかは運次第らしい。 そして待つこと9時間・・・でけた。

sudo mdadm --detail /dev/md0
/dev/md0:
        Version : 1.2
  Creation Time : Sat Apr  2 20:56:11 2011
     Raid Level : raid5
     Array Size : 5860541952 (5589.05 GiB 6001.19 GB)
  Used Dev Size : 1953513984 (1863.02 GiB 2000.40 GB)
   Raid Devices : 4
  Total Devices : 4
    Persistence : Superblock is persistent

  Intent Bitmap : Internal

    Update Time : Sun Apr 10 18:41:25 2011
          State : active
 Active Devices : 4
Working Devices : 4
 Failed Devices : 0
  Spare Devices : 0

         Layout : left-symmetric
     Chunk Size : 512K

           Name : :RAID6T
           UUID : bf2c60f6:17268f0e:540f68af:22e92873
         Events : 10165

    Number   Major   Minor   RaidDevice State
       0       8       17        0      active sync   /dev/sdb1
       1       8       33        1      active sync   /dev/sdc1
       2       8       49        2      active sync   /dev/sdd1
       4       8        1        3      active sync   /dev/sda1

mdadm は正常だと言っている。でも実際のデータはどうだろうか? 試しにいくつかの映像を見たらまともだったが、まさか全部確認するわけにもいかない。 何かこう、復旧できたって信じられる何かが欲しい。

・・・hash.txtがあるじゃないか。何気にとっておいたhash.txtと復旧したファイルのハッシュを比較すれば良い。 結果は、崩壊時にコピー中だったファイルを除いて正常だった。ふぅ。「うわらば」なんて言わずに済んだ。

■教訓


2011/08/23 AVXあれこれ

Sandy Bridge の持つAVX命令。世間では「対応ソフトが出ればエンコ大幅加速」みたいに言われている。 もっとも個人的には眉唾と思っている。

■x264

Doom9のフォーラムにも同じような話があるが、端的に言って大して効果がないらしい。

そりゃそうだ。動画圧縮の時間の大部分を占める解析段は、ふつう整数演算で事足りる。 AVXは大量の浮動小数点演算をまとめて動かすときだけにしか効かないので、H.264では出番がない。

3オペランド演算にしても、そもそもレジスタ間コピーは相当高速でスループットも高いので、 コピー命令不要になっても大して効果が出ない。むしろ命令長が長くなった悪影響が出ないともかぎらない。

■うにω

実際に作ってみた。うにωの量子化プロセスは fp32 DCT + fp32 対数量子化という豪華な構成。 少なくとも出番はあるはずだが、実際どうよ?

AVXなし AVXあり
32Bit版 167.8秒 167.9秒
64Bit版 161.9秒 161.9秒

わはは。誤差程度。HTの有無に影響されるかと思ってシングルスレッドでも試したが似たような感じだった。 ちなみに実際のコード(DCT部分)はこんな感じ。

SSE版 AVX版
    mov       (eax,8);
L("loop0);
    movdqa    (xmm4,ptr[rsi + 7 * 16]);
    movdqa    (xmm5,ptr[rsi + 4 * 16]);
    movdqa    (xmm0,ptr[rsi + 0 * 16]);
    movdqa    (xmm1,ptr[rsi + 3 * 16]);
    movdqa    (xmm6,ptr[rsi + 6 * 16]);
    movdqa    (xmm2,ptr[rsi + 1 * 16]);
    movdqa    (xmm3,xmm4);
    movdqa    (xmm7,xmm5);
    addps     (xmm4,xmm0);
    addps     (xmm5,xmm1);
    subps     (xmm0,xmm3);
    subps     (xmm1,xmm7);
    movdqa    (xmm3,xmm6);
    movdqa    (xmm7,xmm4);
    addps     (xmm6,xmm2);
    subps     (xmm4,xmm5);
    subps     (xmm2,xmm3);
    addps     (xmm5,xmm7);
             :
    movdqa    (ptr[rsi + 5 * 16],xmm5);
    movdqa    (ptr[rsi + 3 * 16],xmm0);
    movdqa    (ptr[rsi + 2 * 16],xmm6);
    movdqa    (ptr[rsi + 6 * 16],xmm7);
    add       (rsi,128);
    sub       (eax,1);
    jnz       ("loop0");
             :
    
    mov           (eax,4);
L("loop0);
    vmovdqa       (xmm4,ptr[rsi + 7 * 16]);
    vmovdqa       (xmm0,ptr[rsi + 0 * 16]);
    vmovdqa       (xmm6,ptr[rsi + 4 * 16]);
    vmovdqa       (xmm1,ptr[rsi + 3 * 16]);
    vmovdqa       (xmm7,ptr[rsi + 6 * 16]);
    vmovdqa       (xmm2,ptr[rsi + 1 * 16]);
    vinsertf128   (ymm4,ymm4,ptr[rsi + 7 * 16 + 128],1);
    vinsertf128   (ymm0,ymm0,ptr[rsi + 0 * 16 + 128],1);
    vinsertf128   (ymm6,ymm6,ptr[rsi + 4 * 16 + 128],1);
    vinsertf128   (ymm1,ymm1,ptr[rsi + 3 * 16 + 128],1);
    vinsertf128   (ymm7,ymm7,ptr[rsi + 6 * 16 + 128],1);
    vinsertf128   (ymm2,ymm2,ptr[rsi + 1 * 16 + 128],1);
    vaddps        (ymm3,ymm4,ymm0);
    vsubps        (ymm0,ymm0,ymm4);
    vaddps        (ymm4,ymm6,ymm1);
    vsubps        (ymm1,ymm1,ymm6);
    vaddps        (ymm3,ymm7,ymm2);
    vsubps        (ymm2,ymm2,ymm7);
    vsubps        (ymm6,ymm3,ymm4);
    vaddps        (ymm4,ymm4,ymm3);
             :
    vmovdqa       (ptr[rsi + 3 * 16],xmm7);
    vmovdqa       (ptr[rsi + 5 * 16],xmm3);
    vmovdqa       (ptr[rsi + 6 * 16],xmm2);
    vmovdqa       (ptr[rsi + 2 * 16],xmm5);
    vextractf128  (ptr[rsi + 3 * 16 + 128],ymm7,1);
    vextractf128  (ptr[rsi + 5 * 16 + 128],ymm3,1);
    vextractf128  (ptr[rsi + 6 * 16 + 128],ymm2,1);
    vextractf128  (ptr[rsi + 2 * 16 + 128],ymm5,1);
    add           (rsi,256);
    sub           (eax,1);
    jnz           ("loop0");
    vzeroupper    ();

             :
    

この部分は128バイトおきに同じデータ構造がある。そこでYMMの上位と下位に分けて AVX命令で一気に処理してループ数を半減させる。実際、DCTの所だけ抜き出して比較すると AVXの方が1.8倍程速い。

にもかかわらず全体で誤差レベルの差しか出ないのは、やはり整数演算の解析段が大部分を占めるから。 極端にAVXが速くて、例えば整数演算の速度を超えてくれれば使い道があるのだが、残念ながらそこまで速くない。

■おまけ

vzeroupper命令、最初はYMMレジスタの依存性解消のための命令と思っていた。 だからYMMレジスタの下位128Bitをメモリに書き込む際、レジスタ変更がないと思ってmovdqaを使ったが、失敗した。 高速化の効果は見えないのにストールの効果は明白に出る。SSE版より明らかに遅くなってしまった。

インテルのInstruction Set Referenceには「This instruction is recommended when transitioning between AVX and legacy SSE code - it will eliminate performance penalties caused by false dependencies.」とある。

「false dependencies」だけでなく、「transitioning between AVX and legacy SSE」と説明しているあたり、 YMMの上位だけクリアするもんでもないらしい。レジスタ書き換えに関係なく使用命令群が変化した時点で要るようだ。

ストールあり ストールなし
    vaddps       (ymm7,ymm0,ymm3);
    vsubps       (ymm3,ymm3,ymm0);
    vsubps       (ymm2,ymm2,ymm14);
    vaddps       (ymm5,ymm5,ymm6);
    movdqa       (ptr[rsi + 3 * 16],xmm7);
    movdqa       (ptr[rsi + 5 * 16],xmm3);
    movdqa       (ptr[rsi + 6 * 16],xmm2);
    movdqa       (ptr[rsi + 2 * 16],xmm5);
    vextractf128 (ptr[rsi + 3 * 16 + 128],ymm7,1);
    vextractf128 (ptr[rsi + 5 * 16 + 128],ymm3,1);
    vextractf128 (ptr[rsi + 6 * 16 + 128],ymm2,1);
    vextractf128 (ptr[rsi + 2 * 16 + 128],ymm5,1);
    
    vaddps       (ymm7,ymm0,ymm3);
    vsubps       (ymm3,ymm3,ymm0);
    vsubps       (ymm2,ymm2,ymm14);
    vaddps       (ymm5,ymm5,ymm6);
    vmovdqa      (ptr[rsi + 3 * 16],xmm7);
    vmovdqa      (ptr[rsi + 5 * 16],xmm3);
    vmovdqa      (ptr[rsi + 6 * 16],xmm2);
    vmovdqa      (ptr[rsi + 2 * 16],xmm5);
    vextractf128 (ptr[rsi + 3 * 16 + 128],ymm7,1);
    vextractf128 (ptr[rsi + 5 * 16 + 128],ymm3,1);
    vextractf128 (ptr[rsi + 6 * 16 + 128],ymm2,1);
    vextractf128 (ptr[rsi + 2 * 16 + 128],ymm5,1);
    


 

戻る