64bits
linux で 64 ビット環境を構築。そして64ビットマルチプロセス対応プログラムを作る - 志を立てるのに、遅すぎることはない -- by ピカソ河
投稿フォーム:
お名前: ニックネームでも何でもかまいません(必須)
パスワード: なりすまし防止のため利用できます(任意)
記事:
 
キャンセル
52 owa #e8faefa 2008/10/26 22:46 prob:%
メモリ 8GB 積んでみた BIOS, x86_64 ともに無事に認識してるみたい。 http://owa.as.wakwak.ne.jp/zope/docs/PC/GA-MA770-DS3
51 owa #e8faefa 2008/04/29 15:32 prob:%
AMD CPU エラッタ http://pc.nikkeibp.co.jp/article/news/20080428/1001503/ B2 Stepping でのバグ Phenom 9500/9600/9600 Black Edition、同X3 8400/8600、同X4 9100e B3 Stepping では解消されているらしい Phenom X4 9550/9650/9750/9850 Black Edition、同X3 8450/8650/8750
50 owa #e8faefa 2008/03/11 21:41 prob:%
C128クラスの更新 http://owa.as.wakwak.ne.jp/zope/docs/C/C128 getofs() - 追加: ビット位置を整数で返すメソッド getbit() - 追加: 最下位ビットを返すメソッド。そのたび最下位ビットを0にする。 getlsb() - 更新: 高速化 (10%)
49 owa #e8faefa 2007/11/11 23:27 prob:%
C128クラスにLSB,MSB関数を追加 http://owa.as.wakwak.ne.jp/zope/docs/C/C128 上記128ビット型クラスに getlsb(), getmsb() を追加しました。 C128 C128::getlsb() const { ULong x = -hi; if (lo) --x; return C128(lo & (-lo), hi & x); } C128 C128::getmsb() const { ULong x = (hi)? hi: lo; x |= (x >> 1); x |= (x >> 2); x |= (x >> 4); x |= (x >> 8); x |= (x >> 16); x |= (x >> 32); x &= ~(x >> 1); return (hi)? C128(0, x): C128(x); }
48 owa #e8faefa 2007/11/09 23:30 prob:%
nasm 0.99 サンプルコード sse レジスタにコピーして左に 8bits シフトするだけです。 64 ビット境界を越えてシフトされません。 ---------------------------- bits 64 section .text global bitshift128 bitshift128 movupd xmm0, [rdi] psllq xmm0, 8 ; shift left 8bits movq rax, xmm0 psrldq xmm0, 8 ; shift right 8bytes movq rdx, xmm0 ret --------------------------- 呼び出し側 void test3() { struct U128 {unsigned long long lo, hi;} src; src.lo = 0x4444444488888888LL; src.hi = 0x1111111122222222LL; fprintf(stderr, "src=0x%016llx%016llx\n", src.hi, src.lo); U128 dst = bitshift128(&src); fprintf(stderr, "dst=0x%016llx%016llx\n", dst.hi, dst.lo); } 実行結果 src=0x11111111222222224444444488888888 dst=0x11111122222222004444448888888800 参考サイト http://www.cs.uaf.edu/2007/fall/cs301/support/x86_64/index.html
47 owa #e8faefa 2007/11/09 22:50 prob:%
SSE の利用は難しい;; ビット移動を伴う命令が 64bit までしか対応していないのかな (paddq, psubq, psllq, psrlq)。 バイト単位のシフトは pslldq, psrldq があるけど、ビットシフトを作るのは少し大変。 あまり汎用ロジック向けには作ってないってことでしょうか。 ただメモリ対128ビットレジスタ間のコピーは movupd, movntdq でダイレクトにできるようだし、 XOR, OR, AND, NOT は pxor, por, pand 使えばできることが解った。 いつか役に立つ日が来るかもしれない。
46 owa #e8faefa 2007/11/07 21:58 prob:%
SSE にはビットシフト命令が無い;; http://web.mit.edu/nasm_v0.98/doc/nasm/html/nasmdoc0.html あるのはバイト単位のシフト演算のみ。 とりあえず SSE 128bit レジスタに入れて出すだけのコード。(信用しないで!) void test2() { typedef struct {ULong lo; ULong hi;} U128; U128 m, n; m.hi = 0x1111111111111111; m.lo = 0x2222222222222222; n.hi = 0; n.lo = 0; __asm__ __volatile__ ( "movq %2, %%xmm0;" "movq %3, %%xmm1;" "pslldq $8, %%xmm0;" "orps %%xmm0, %%xmm1;" "movq %%xmm1, %1;" "psrldq $8, %%xmm1;" "movq %%xmm1, %0;" : "=m"(n.hi), "=m"(n.lo) // n is output operand (%0, %1) : "m"(m.hi), "m"(m.lo) // m is input operand (%2, %3) : "%xmm0", "%xmm1" // clobbered register ); fprintf(stderr, "m=0x%016llx%016llx, n=0x%016llx%016llx\n", m.hi, m.lo, n.hi, n.lo); } 実行結果は m=0x11111111111111112222222222222222, n=0x11111111111111112222222222222222 128ビット空間を自由に使えるものだと思ってた。馬鹿ですね。 シフト演算はたし算 (とバイト単位のシフトも使う?) に置き換えればできるけど、どうなんだろう? C/C++ の 64ビットx2 のデータではシフト演算のロジックが汚くなるので SSE まで逃げてきたんだけど、 GPU と連立組むのもアイディアのうちか。 参考サイト: Optimizing MILC Math Routines with SSE http://lqcd.fnal.gov/sse/ SSE2を用いたRC5-64クライアントの最適化に関する考察 http://www.katto.comm.waseda.ac.jp/~matsui/rc5/index.html 続 GeForce8800GTX と SM4.0 の整数演算 http://wlog.flatlib.jp/item/911/catid/6 NVIDIA CUDA Homepage http://developer.nvidia.com/object/cuda.html
45 owa #e8faefa 2007/11/06 22:44 prob:%
インラインアセンブラの勉強 GCC Inline Assembler http://caspar.hazymoon.jp/OpenBSD/annex/gcc_inline_asm.html http://caspar.hazymoon.jp/OpenBSD/annex/gas.html http://www.mars.sannet.ne.jp/sci10/on_gcc_asm.html void test1() { typedef unsigned long long ULong; ULong m = 0x1000100010001000; ULong n = 0x0111011101110111; ULong out = 0; __asm__ __volatile__ ( "movq %1, %%rax;" "addq %2, %%rax;" "movq %%rax, %0;" : "=r"(out) // 出力 (%0) : "r"(m), "r"(n) // 入力 (%1, %2) : "%rax" // 破壊されるレジスタ ); fprintf(stderr, "m=0x%016llx, n=0x%016llx, out=0x%016llx\n", m, n, out); } コンパイル (gcc -m64) 後の実行結果は m=0x1000100010001000, n=0x0111011101110111, out=0x1111111111111111
44 owa #e8faefa 2007/11/03 22:44 prob:%
ビット位置の計算 0.0065秒/100万 (gcc -O3 Athlon64x2 3800+ x86_64 vine seed) 0.0146秒/100万 (gcc -O3 Athlon64x2 3800+ i386 vine 4.1) ただ1ビットだけ立ってる場合のオフセットを求める方法。 --- int offset_of_onebit1(unsigned long long x) { int n = 0; if (x & 0xffffffff00000000LL) { n += 32; x >>= 32; } if (x & 0xffff0000) n += 16; if (x & 0xff00ff00) n += 8; if (x & 0xf0f0f0f0) n += 4; if (x & 0xcccccccc) n += 2; if (x & 0xaaaaaaaa) n += 1; return n; } --- n += 16 は n |= 16 でも同じ。むしろ若干遅くなる。 また以下のように if 文を無くしても処理速度は変わらない --- int offset_of_onebit2(ULong x) { int n = 0; (x & 0xffffffff00000000LL) && (n += 32) && (x >>= 32); (x & 0xffff0000) && (n += 16); (x & 0xff00ff00) && (n += 8); (x & 0xf0f0f0f0) && (n += 4); (x & 0xcccccccc) && (n += 2); (x & 0xaaaaaaaa) && (n++); return n; } --- 環境によって違いはあるかも。
43 owa #e8faefa 2007/10/29 22:37 prob:%
ビットの連続抽出 0.230秒/100万 (gcc -O3 Athlon64x2 3800+ x86_64 vine seed) 0.513秒/100万 (gcc -O3 Athlon64x2 3800+ i386 vine 4.1) ビット位置を一個ずつ取り出すイテレータ。 肝は bits & (-bits) で LSB (Least Significant Bit) が求められること。 --- #if defined(__x86_64__) typedef unsigned long ULong; #elif defined(__i386__) typedef unsigned long long ULong; #endif class CBitPos { ULong bits; public: CBitPos(ULong x) : bits(x) {} ULong next() { ULong x = bits & (-bits); bits &= ~x; return x; } }; --- 一回あたり44ビットONのデータで測定。つまり一個のイテレータで44回ループ処理した。 for (long i = 0; i < 1000000L; i++) { CBitPos a(0x7777777777773333LL); int pos = a.next(); while (pos) pos = a.next(); } ちなみに MSB (Most Significant Bit) を求める方法を用いると三倍くらい遅くなる。 --- x |= (x >> 1); x |= (x >> 2); x |= (x >> 4); x |= (x >> 8); x |= (x >> 16); x |= (x >> 32); x &= ~(x >> 1); ---