2010/06/18


今じゃぁgcc4が一般的なので、状況変わったかな?と思ったのでWindowsで再度試してみた。
Big Sky :: シャア専用memcpy

試してみた memcpy 最適化 - id:kazuhookuのメモ置き場バイト単位でコピーするアホなコードの方が、勝手にベクトル化される分、gcc 内蔵のヤツより最大3倍高速なんだってwwwx64じ...

http://mattn.kaoriya.net/software/gcc/20080617134829.htm
前回は効果が無かったけど、今回は --------------------------------------------------------------------------
gcc (GCC) 4.4.0
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
--------------------------------------------------------------------------

# gcc -O3 -ftree-vectorize -msse2 test.c

adhock memcpy: 1.625031
normal memcpy: 3.734447

# gcc -O3 -ftree-vectorize -ftree-vectorizer-verbose=5 -mmmx -msse3 test.c

adhock memcpy: 1.609581
normal memcpy: 3.750480

# gcc test.c

adhock memcpy: 79.642154
normal memcpy: 4.968845

確かに3倍近いスコアが出てる。もうmemcpyとかinlineでいいんでね?
Posted at by




golangタグが既におかしいですが...
// ; hello world on win32 writen in asm.
// ; compile: 8a helloworld.s
// ; link   : 8l -o helloworld.exe helloworld.8
// ; run    : helloworld.exe
// ; 
// ; if you get the following compile error,
// ;   maybe, namespace separator was broken by copy-and-paste.
// ; open this file with text editor as utf-8 encoding, and fix following...
// ;
// ;   main!main
// ;   main!init
// ;   runtime!printstring
// ;
// ; ! should be code point 183 in unicode.

// ; main.main
TEXT    main·main+0(SB),$16-0
LEAL    gstring+0(SB),SI
LEAL    (SP),DI
CLD     ,
MOVSL   ,
MOVSL   ,
CALL    ,runtime·printstring+0(SB)
RET

// ; main.init
TEXT    main·init+0(SB),$4-0
RET

// ; data for native
GLOBL   string+0(SB),$14
DATA    string+0(SB)/8,$"hello, w"
DATA    string+8(SB)/7,$"orld!\n\z"

// ; data for gostring
GLOBL   gstring+0(SB),$8
DATA    gstring+0(SB)/4,$string+0(SB)
DATA    gstring+4(SB)/4,$13
END     ,
goではplan9形式のアセンブリで書けば8a(6a)でコンパイルでき、8l(6l)でリンク出来るので、上のソースをコンパイルすると見事に「hello, world!」と表示される。plan9のアセンブリってアライメントが必要なのね...。あと文字列リソースはgostring用と分けて書かないとlengthが違っちゃうみたい。

途中にある変な文字「·」はutf-8で183のコードポイントです。
gist: 434256 - GitHub

hello world on win32 writen in asm.

http://gist.github.com/434256
Posted at by




tyruさんが既に記事にしてくれてますが、こちらでも。
mattnさんが前の記事にコードで回答してくれた - おつあり

mattnさんが前の記事にコードで回答してくれた Vim mattn’s libcallex-vim at master - GitHub こんなリポジトリが作られたので十中八九僕のlibcall()...

http://d.hatena.ne.jp/tyru/20100518/cool_mattn
通常 libcall は引数が1つしか扱えないのですが、内部でJSONでやりとりしてC言語で書いた呼び出しproxyを介して外部ライブラリ(DLL等)の関数を呼び出せます。
とはいってもvimで扱える型しか対応していませんが、ちょっと無茶すればいろんな事が出来ます。
例えばuser32.dllのMessageBoxAを実行したり... so ../libcallex.vim

silent unlet! lib

let lib = libcallex.load('msvcrt.dll')
let username = lib.call('getenv', ["USERNAME"], 'string')
call libcallex.free(lib)

let lib = libcallex.load("user32.dll")
if lib.call('MessageBoxA', [0, "Hello ".username."\r\nCan you see this message?", 'Hello World', 4]) == 6
  call lib.call('MessageBoxA', [0, 'You clicked "YES"', 'Hello World', 0])
else
  call lib.call('MessageBoxA', [0, 'You clicked "NO". Are you all right?', 'Hello World', 0])
endif
call libcallex.free(lib)
バッファを引数に取る関数を呼び出してWindowsのSystemディレクトリを取得したり... so ../libcallex.vim

silent unlet! lib

let lib = libcallex.load('kernel32.dll')

let buf = repeat(' ', 255)
let args = [buf, 255]
call lib.call('GetWindowsDirectoryA', args, 'number')
let dir = args[0]
echo "your windows directory: " . dir

let buf = repeat(' ', 255)
let args = [buf, 255]
call lib.call('GetSystemDirectoryA', args, 'number')
let dir = args[0]
echo "your system directory : " . dir

call libcallex.free(lib)
無理やりlongのポインタ作ってバッファ書き込み数を参照渡しで扱う関数を呼び出したり... so ../libcallex.vim

silent unlet! msvcrt
silent unlet! advapi32

let msvcrt = libcallex.load('msvcrt.dll')
let advapi32 = libcallex.load('advapi32.dll')

" make address of variable which is stored 256
let ptr = float2nr(eval(msvcrt.call('malloc', [4], 'number')))
call msvcrt.call('memset', [ptr, 0, 4], 'number')
call msvcrt.call('memset', [ptr+1, 1, 1], 'number')

let buf = repeat(' ', 256)
let args = [buf, ptr]
call advapi32.call('GetUserNameA', args, 'number')
let username = args[0]

call msvcrt.call('free', [ptr], 'number')

call libcallex.free(advapi32)
call libcallex.free(msvcrt)

echo username
出来ます。(まぁ最後のはやりすぎとして)
分かる人は想像通りですが、簡単なインラインアセンブラで実現してます。
いままでvimからDLL呼び出しが出来ないと悩んでおられた方には有用かもしれません。

えっ?mattnとtyruさんだけだって?
Posted at by