|
|
||
SIMD | |
で、さっきのコードなんだけど、ふつうに ``+'' で書くのと intrinsics 使うのとでは生成されるコードがちがう。
uint4 x = {0,1,2,3};
uint4 y = {4,5,6,7};
uint4 result = x + y;
-[neon_01AppDelegate sum]:
0000000c b5f0 push {r4, r5, r6, r7, lr}
0000000e af03 add r7, sp, #12
00000010 b085 sub sp, #20
00000012 a30a add r3, pc, #40 (adr r3, 0x3c)
00000014 cb78 ldmia r3, {r3, r4, r5, r6}
00000016 480d ldr r0, [pc, #52] (0x4c)
00000018 ec443b16 vmov d6, r3, r4
0000001c ec465b17 vmov d7, r5, r6
00000020 ed8d6b01 vstr d6, [sp, #4]
00000024 ed8d7b03 vstr d7, [sp, #12]
uint4 x = {0,1,2,3};
uint4 y = {4,5,6,7};
uint4 result = vaddq_u32(x, y);
-[neon_01AppDelegate sum]:
0000007c b580 push {r7, lr}
0000007e af00 add r7, sp, #0
00000080 b085 sub sp, #20
00000082 ed9f4b0c vldr d4, [pc, #48] ; 0xb6
00000086 ed9f5b0d vldr d5, [pc, #52] ; 0xbe
0000008a ed9f6b0e vldr d6, [pc, #56] ; 0xc6
0000008e ed9f7b0f vldr d7, [pc, #60] ; 0xce
00000092 ef266844 vadd.i32 q3, q3, q2
00000096 ed8d6b01 vstr d6, [sp, #4]
0000009a ed8d7b03 vstr d7, [sp, #12]
解読中。
SIMD | |
iPhone 3GS / touch 3G では、ARM の NEON SIMD 命令が使えて胸がときめきます。ほんの少し設定すれば Xcode からもつかえる。
"-march=armv7-a -mtune=cortex-a8 -mfloat-abi=softfp -mfpu=neon" を CFLAGS につけないといけないかなーと思ってたんですが、つけたのとついてないのとで、吐かれるアセンブリが変わらないんですよね。なぞ。もっと複雑な SIMD 書くと違ってくるのかも。要追求。
iPhone 3GS か touch 3G な実機でしか動きません。
gist: 222087 - sum by ARM NEON- GitHub
- (void) sum { uint4 x = {0,1,2,3}; uint4 y = {4,5,6,7}; //uint4 result = x + y; uint4 result = vaddq_u32(x, y); uint32_t a = *(uint32_t *)&result; uint32_t b = *((uint32_t *)&result +1); uint32_t c = *((uint32_t *)&result +2); uint32_t d = *((uint32_t *)&result +3); NSLog(@"result = (%u,%u,%u,%u)", a, b, c, d); // -> result = (4,6,8.10) }
結果:
% /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/otool -tV build/neon_01.build/Release-iphoneos/neon_01.build/Objects-normal/armv7/neon_01AppDelegate.o
....
-[neon_01AppDelegate sum]:
0000007c b580 push {r7, lr}
0000007e af00 add r7, sp, #0
00000080 b085 sub sp, #20
00000082 ed9f4b0c vldr d4, [pc, #48] ; 0xb6
00000086 ed9f5b0d vldr d5, [pc, #52] ; 0xbe
0000008a ed9f6b0e vldr d6, [pc, #56] ; 0xc6
0000008e ed9f7b0f vldr d7, [pc, #60] ; 0xce
00000092 ef266844 vadd.i32 q3, q3, q2
00000096 ed8d6b01 vstr d6, [sp, #4]
0000009a ed8d7b03 vstr d7, [sp, #12]
....
2.2.1 時代からあるプロジェクトを、さて 3.0 用にビルドするかいな、とやってみるとコンパイルエラーになった。
なんぞこれ、と調べてるうち、 GCC 4.0 なのがまずそうな。 プロジェクトの設定から、コンパイラのバージョンを GCC 4.2 にすると OK 。
see also: Offline - Stack Overflow
ちょっとしたはまり解決 tips でした。
vfp | |
3GS が速いそうですね。うらやましくないもん! 我々には VFP があるんじゃないの!
ということで VFP (Vector Floating Point co-processor) を調べてた。
Sketchbook: iPhone VFP for n00bs のチュートリアルがわかりやすい。
Xcode で新規プロジェクトをつくり、 vfp.[ch] なんてファイルを追加して
vfp.c: void test(float * src, float * dst) { __asm__ volatile ( "fldmias %0!, {s8-s11} \n\t" // operations "fstmias %1!, {s8-s11} \n\t" : "=r" (src), "=r" (dst) // output operands : "0" (src), "1" (dst) // input operands : "memory" // clobbers ); } vfp.h: void test(float * src, float * dst);
とか書き、ViewController とかから確認:
- (void)viewDidLoad { [super viewDidLoad]; float src[4] = {0.1f, 0.2f, 0.3f, 0.4f}, dst[4] = {0.0f, 0.0f, 0.0f, 0.0f}; test(src, dst); NSLog(@"%f %f %f %f", dst[0], dst[1], dst[2], dst[3]); }
fldmias は f "LoaD" m ia s で、SIMD でロードする命令。 fstmias は f "STore" m ia s で、 SIMD でストアする命令。
ia とか s とかの詳細については ARM のリファレンスなどをみるとよいとおもいます。
そのままビルドしようとすると、
> selected processor does not support `fldmias r2!,{s8-s11}`
などとコンパイラにおこられたりするので、ターゲット → 情報を見る から、'compiled for thumb' のチェックボックスをオフにするとうまくいったりする。
これで VFP であそぶ下地ができましたね。
mootoh’s PictureSharingIPhone at master - GitHub
Mac の Bonjour サンプルで PictureSharing というのがあり、 iPhone でも同じように使えるように移植してみた。
ほとんどそのまま使えてすばらすい。 Cocoa すごい。
プロジェクト内で、 .m なファイルがなくなると、プロジェクトのプロパティから GCC のコンパイラオプションが消えてしまうことに気づいた。
あとからプロジェクトに .m なファイルを追加すると、コンパイラオプションが出てくることもあるし、出てこないこともある。
Xcode がとちくるってるんじゃ? と思い、 Xcode の設定ファイルを消して再チャレンジしてみた。いまのところうまくいってる。謎...
Base SDK が Device のときに、 Active SDK を Device にしたらコンパイラオプションがでてきた。 Simulator にしたら消える。逆もまたしかり。そういうものだっけ?
execinfo.h をつかったバックトレースは、 iPhone でもできるよという話。シミュレータ、実機のどちらでもOK。
コード: main.m
#include <execinfo.h> void func() { int j, nptrs; #define SIZE 100 void *buffer[SIZE]; char **strings; nptrs = backtrace(buffer, SIZE); NSLog(@"backtrace() returned %d addresses\n", nptrs); strings = backtrace_symbols(buffer, nptrs); if (strings == NULL) { perror("backtrace_symbols"); exit(EXIT_FAILURE); } for (j = 0; j < nptrs; j++) NSLog(@"%s\n", strings[j]); free(strings); } int main(int argc, char *argv[]) { func(); return 0; }
実機で動かした結果:
2009-02-28 17:12:25.864 minimal[647:20b] backtrace() returned 3 addresses 2009-02-28 17:12:25.886 minimal[647:20b] 0 minimal 0x00002081 start + 129 2009-02-28 17:12:25.897 minimal[647:20b] 1 minimal 0x000020f5 start + 245 2009-02-28 17:12:25.908 minimal[647:20b] 2 minimal 0x00002034 start + 52
なぜこれがバックトレースなのか:
% otool -tv build/Release-iphoneos/minimal.app/minimal build/Release-iphoneos/minimal.app/minimal: (__TEXT,__text) section start: 00002000 e59d0000 ldr r0, [sp] ... _func: 0000206c b5f0 push {r4, r5, r6, r7, lr} 0000206e 4656 mov r6, r10 ... _main: 000020ec b580 push {r7, lr} 000020ee af00 add r7, sp, #0 000020f0 ffbcf7ff bl 0x206c 000020f4 2000 mov r0, #0 000020f6 bd80 pop {r7, pc}
0x2034 は start, 0x20f5 は _main, 0x2081 は _func の中にあることがわかりますね。