ãšã³ããªãŒ
æè¿ãGPGPUã«é¢ããããŸããŸãªèšäºããã¬ãŒã³ããŒã·ã§ã³ãèªãã åŸããããªã«ãŒãã®ããã°ã©ãã³ã°ãèªåã§è©ŠããŠã¿ãããšã«ããŸããã å®éããã®åéã§ã®æè¡ã®éžæã¯çŽ æŽããããã®ã§ã¯ãããŸãã-CUDAïŒnVidiaç¬èªã®æšæºïŒãšOpenCLïŒç¡æã®æšæºãATIã®GPUãnVidiaãããã³äžå€®åŠçè£ çœ®ïŒã®ã¿ããŸã çããŠãããéçºäžã§ãã ç§ã®ã©ãããããã«ã¯ATIã°ã©ãã£ãã¯ã«ãŒãïŒMobility Radeon 5650 HDïŒããããããéžæè¢ã¯å®å šã«1ã€ã®ãªãã·ã§ã³-OpenCLã«éå®ãããŸããã ãã®èšäºã§ã¯ãOpenCLããŒãããåŠç¿ããããã»ã¹ãšããã®èµ·æºã«ã€ããŠèª¬æããŸãã
OpenCLããã³PyOpenClã®æŠèŠ
äžèŠãããšãCã®å¶åŸ¡ã³ãŒããšãããããã«ãŒãã«ïŒã«ãŒãã«ïŒã®ã³ãŒãã®äž¡æ¹ããéåžžã«æ··ä¹±ããŠããããã«èŠããŸããã æäŸãããŠããC APIã§ã¯ãç¹ã«å°ãªããšãããã€ãã®ãšã©ãŒã®åŠçã§ã¯ãåçŽãªããã°ã©ã ã®èµ·åã§ããå€ãã®è¡ãå¿ èŠãšããããããã䟿å©ã§äººéçãªãã®ãèŠã€ããããšæããŸããã ãã®éžæã¯PyOpenCLã©ã€ãã©ãªã«ããã£ãŠããŸããããã®ååãããå¶åŸ¡ã³ãŒãã¯Pythonã§æžãããŠããããšãæããã§ãã OpenCLã³ãŒããåããŠèŠã人ã§ãããã¹ãŠãããç解ããããããã«èŠããŸãïŒãã¡ãããããã¯åçŽãªäŸã«ã®ã¿é©çšãããŸãïŒã ãã ããã«ãŒãã«èªäœã®ã³ãŒãã¯ãŸã ãããã«å€æŽãããCã§èšè¿°ãããŠããããããŸã åŠç¿ããå¿ èŠããããŸãã ããã«é¢ããå®å šãªããã¥ã¡ã³ãã¯ãæšæºã®éçºè ã®Webãµã€ãïŒ Khronos ïŒã§å ¥æã§ããç¹å®ã®å®è£ ã«é¢ããæ å ±ã¯ãããããATIããã³nVidia Webãµã€ãã§å ¥æã§ããŸãã
æãç°¡åãªäŸïŒ2ã€ã®é åãè¿œå ïŒã䜿çšããŠãèšèªã®ç¬¬äžå°è±¡ãåŸãããšãã§ããŸãã
__kernel void sum(__global const float *a, __global const float *b, __global float *c) { int gid = get_global_id(0); c[gid] = a[gid] + b[gid]; }
ãããŠããã®äŸãå®è¡ããŠæ€èšŒããããã«å¿ èŠãªå®å šãªã³ãŒãã¯æ¬¡ã®ãšããã§ãïŒPyOpenCLããã¥ã¡ã³ãããååŸïŒã
é衚瀺ã®ããã¹ã
import pyopencl as cl import numpy import numpy.linalg as la a = numpy.random.rand(50000).astype(numpy.float32) b = numpy.random.rand(50000).astype(numpy.float32) ctx = cl.create_some_context() queue = cl.CommandQueue(ctx) mf = cl.mem_flags a_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=a) b_buf = cl.Buffer(ctx, mf.READ_ONLY | mf.COPY_HOST_PTR, hostbuf=b) dest_buf = cl.Buffer(ctx, mf.WRITE_ONLY, b.nbytes) prg = cl.Program(ctx, """ __kernel void sum(__global const float *a, __global const float *b, __global float *c) { int gid = get_global_id(0); c[gid] = a[gid] + b[gid]; } """).build() prg.sum(queue, a.shape, None, a_buf, b_buf, dest_buf) a_plus_b = numpy.empty_like(a) cl.enqueue_copy(queue, a_plus_b, dest_buf) print la.norm(a_plus_b - (a+b))
ç¹å®ã®è¡ãããã«è¡šç€ºãããŸãïŒã³ã³ããã¹ãã®äœæãå®è¡ãã¥ãŒãããã€ã¹ãžã®ãããã¡ãŒã®äœæãšã³ããŒãã«ãŒãã«èªäœã®ã³ã³ãã€ã«ãšèµ·åã OpenCLã®ã³ã³ããã¹ããšãã¥ãŒã®è©³çŽ°ã«ã€ããŠã¯ããã¥ã¡ã³ããåç §ããŠãã ãããæ¯èŒçåçŽãªããã°ã©ã ã®å Žåãå¿ èŠãªãã¥ãŒãšã³ã³ããã¹ãã¯1ã€ã ãã§ãããããã¯ãäŸãšéåžžã«ãã䌌ãè¡ã§äœæãããŸãã äžè¬ã«ãOpenCLããã°ã©ã ã®èšç®ã®æ§é ã¯æ¬¡ã®ããã«ãªããŸãã
- ã³ã³ããã¹ãã®äœæããã¥ãŒãããã°ã©ã ã®ã³ã³ãã€ã«
- å®è¡äžã«å€æŽãããªãããã€ã¹ããŒã¿ïŒãããã¡ïŒãžã®ã³ããŒ
- ãµã€ã¯ã«
- ãã®å埩ã«åºæã®ããŒã¿ãããã€ã¹ã«ã³ããŒãã
- ã«ãŒãã«å®è¡
- èšç®ãããããŒã¿ãã¡ã€ã³ã¡ã¢ãªã«ã³ããŒããŠãäœããã®åŠçãå¯èœ
SHA1ããã·ã¥
ã¬ãã«ãäžããŠãã«ãŒãã«ã³ãŒããã©ã®ããã«æ©èœããããç解ãããšããæ¥ãŸããã OpenCLé¢æ°ãå€éšããå®è¡ããã«ã¯ã__ kernelå±æ§ã§æå®ããå¿ èŠããããå€ã®åãvoidã§ãããçŽæ¥å€ïŒintãfloat4ã...ïŒãŸãã¯é åãžã®ãã€ã³ã¿ãŒã§ããç¹å®ã®æ°ã®åŒæ°ãå¿ èŠã§ãã¡ã¢ãª__globalã__ constantã__ localã ãŸãã䟿å®äžãã«ãŒãã«ããåŒã³åºãããšãã§ããä»ã®é¢æ°ãããã°ã©ã ã§å®£èšã§ããŸãããããã¯ããã©ãŒãã³ã¹ã«åœ±é¿ãäžããŸããããã¹ãŠã®é¢æ°ã¯èªåçã«çœ®ãæããããŸãïŒã€ãŸããã€ã³ã©ã€ã³ãã£ã¬ã¯ãã£ããšåæ§ïŒã ããã¯ãOpenCLã®ååž°ããŸã£ãããµããŒããããŠããªãããã§ãã
OpenCLãå€æŽãããCèšèªã§ãããšããäºå®ã䜿çšããŠãSHA1ãªã©ã®ããã·ã¥é¢æ°ã®æ¢è£œã®å®è£ ã䜿çšããããããªå€æŽã䜿çšã§ããŸãã
é衚瀺ã®ããã¹ã
#define K1 0x5A827999 #define K2 0x6ED9EBA1 #define K3 0x8F1BBCDC #define K4 0xCA62C1D6 #define a0 0x67452301; #define b0 0xEFCDAB89; #define c0 0x98BADCFE; #define d0 0x10325476; #define e0 0xC3D2E1F0; #define f1(x,y,z) ( z ^ ( x & ( y ^ z ) ) ) /* Rounds 0-19 */ #define f2(x,y,z) ( x ^ y ^ z ) /* Rounds 20-39 */ #define f3(x,y,z) ( ( x & y ) | ( z & ( x | y ) ) ) /* Rounds 40-59 */ #define f4(x,y,z) ( x ^ y ^ z ) /* Rounds 60-79 */ #define ROTL(n,X) ( ( ( X ) << n ) | ( ( X ) >> ( 32 - n ) ) ) #define expand(W,i) ( W[ i & 15 ] = ROTL( 1, ( W[ i & 15 ] ^ W[ (i - 14) & 15 ] ^ \ W[ (i - 8) & 15 ] ^ W[ (i - 3) & 15 ] ) ) ) #define subRound(a, b, c, d, e, f, k, data) \ ( e += ROTL( 5, a ) + f( b, c, d ) + k + data, b = ROTL( 30, b ) ) #define REVERSE(value) value = ((value & 0xFF000000) >> 24) | ((value & 0x00FF0000) >> 8) | ((value & 0x0000FF00) << 8) | ((value & 0x000000FF) << 24) long sha1(uint *eData, const int length) { unsigned int A = a0; unsigned int B = b0; unsigned int C = c0; unsigned int D = d0; unsigned int E = e0; ((__local char *)eData)[length] = 0x80; for (int i = 0; i <= length / 4; i++) { REVERSE(eData[i]); } eData[14] = 0; eData[15] = length * 8; subRound( A, B, C, D, E, f1, K1, eData[ 0 ] ); subRound( E, A, B, C, D, f1, K1, eData[ 1 ] ); subRound( D, E, A, B, C, f1, K1, eData[ 2 ] ); subRound( C, D, E, A, B, f1, K1, eData[ 3 ] ); subRound( B, C, D, E, A, f1, K1, eData[ 4 ] ); subRound( A, B, C, D, E, f1, K1, eData[ 5 ] ); subRound( E, A, B, C, D, f1, K1, eData[ 6 ] ); subRound( D, E, A, B, C, f1, K1, eData[ 7 ] ); subRound( C, D, E, A, B, f1, K1, eData[ 8 ] ); subRound( B, C, D, E, A, f1, K1, eData[ 9 ] ); subRound( A, B, C, D, E, f1, K1, eData[ 10 ] ); subRound( E, A, B, C, D, f1, K1, eData[ 11 ] ); subRound( D, E, A, B, C, f1, K1, eData[ 12 ] ); subRound( C, D, E, A, B, f1, K1, eData[ 13 ] ); subRound( B, C, D, E, A, f1, K1, eData[ 14 ] ); subRound( A, B, C, D, E, f1, K1, eData[ 15 ] ); subRound( E, A, B, C, D, f1, K1, expand( eData, 16 ) ); subRound( D, E, A, B, C, f1, K1, expand( eData, 17 ) ); subRound( C, D, E, A, B, f1, K1, expand( eData, 18 ) ); subRound( B, C, D, E, A, f1, K1, expand( eData, 19 ) ); subRound( A, B, C, D, E, f2, K2, expand( eData, 20 ) ); subRound( E, A, B, C, D, f2, K2, expand( eData, 21 ) ); subRound( D, E, A, B, C, f2, K2, expand( eData, 22 ) ); subRound( C, D, E, A, B, f2, K2, expand( eData, 23 ) ); subRound( B, C, D, E, A, f2, K2, expand( eData, 24 ) ); subRound( A, B, C, D, E, f2, K2, expand( eData, 25 ) ); subRound( E, A, B, C, D, f2, K2, expand( eData, 26 ) ); subRound( D, E, A, B, C, f2, K2, expand( eData, 27 ) ); subRound( C, D, E, A, B, f2, K2, expand( eData, 28 ) ); subRound( B, C, D, E, A, f2, K2, expand( eData, 29 ) ); subRound( A, B, C, D, E, f2, K2, expand( eData, 30 ) ); subRound( E, A, B, C, D, f2, K2, expand( eData, 31 ) ); subRound( D, E, A, B, C, f2, K2, expand( eData, 32 ) ); subRound( C, D, E, A, B, f2, K2, expand( eData, 33 ) ); subRound( B, C, D, E, A, f2, K2, expand( eData, 34 ) ); subRound( A, B, C, D, E, f2, K2, expand( eData, 35 ) ); subRound( E, A, B, C, D, f2, K2, expand( eData, 36 ) ); subRound( D, E, A, B, C, f2, K2, expand( eData, 37 ) ); subRound( C, D, E, A, B, f2, K2, expand( eData, 38 ) ); subRound( B, C, D, E, A, f2, K2, expand( eData, 39 ) ); subRound( A, B, C, D, E, f3, K3, expand( eData, 40 ) ); subRound( E, A, B, C, D, f3, K3, expand( eData, 41 ) ); subRound( D, E, A, B, C, f3, K3, expand( eData, 42 ) ); subRound( C, D, E, A, B, f3, K3, expand( eData, 43 ) ); subRound( B, C, D, E, A, f3, K3, expand( eData, 44 ) ); subRound( A, B, C, D, E, f3, K3, expand( eData, 45 ) ); subRound( E, A, B, C, D, f3, K3, expand( eData, 46 ) ); subRound( D, E, A, B, C, f3, K3, expand( eData, 47 ) ); subRound( C, D, E, A, B, f3, K3, expand( eData, 48 ) ); subRound( B, C, D, E, A, f3, K3, expand( eData, 49 ) ); subRound( A, B, C, D, E, f3, K3, expand( eData, 50 ) ); subRound( E, A, B, C, D, f3, K3, expand( eData, 51 ) ); subRound( D, E, A, B, C, f3, K3, expand( eData, 52 ) ); subRound( C, D, E, A, B, f3, K3, expand( eData, 53 ) ); subRound( B, C, D, E, A, f3, K3, expand( eData, 54 ) ); subRound( A, B, C, D, E, f3, K3, expand( eData, 55 ) ); subRound( E, A, B, C, D, f3, K3, expand( eData, 56 ) ); subRound( D, E, A, B, C, f3, K3, expand( eData, 57 ) ); subRound( C, D, E, A, B, f3, K3, expand( eData, 58 ) ); subRound( B, C, D, E, A, f3, K3, expand( eData, 59 ) ); subRound( A, B, C, D, E, f4, K4, expand( eData, 60 ) ); subRound( E, A, B, C, D, f4, K4, expand( eData, 61 ) ); subRound( D, E, A, B, C, f4, K4, expand( eData, 62 ) ); subRound( C, D, E, A, B, f4, K4, expand( eData, 63 ) ); subRound( B, C, D, E, A, f4, K4, expand( eData, 64 ) ); subRound( A, B, C, D, E, f4, K4, expand( eData, 65 ) ); subRound( E, A, B, C, D, f4, K4, expand( eData, 66 ) ); subRound( D, E, A, B, C, f4, K4, expand( eData, 67 ) ); subRound( C, D, E, A, B, f4, K4, expand( eData, 68 ) ); subRound( B, C, D, E, A, f4, K4, expand( eData, 69 ) ); subRound( A, B, C, D, E, f4, K4, expand( eData, 70 ) ); subRound( E, A, B, C, D, f4, K4, expand( eData, 71 ) ); subRound( D, E, A, B, C, f4, K4, expand( eData, 72 ) ); subRound( C, D, E, A, B, f4, K4, expand( eData, 73 ) ); subRound( B, C, D, E, A, f4, K4, expand( eData, 74 ) ); subRound( A, B, C, D, E, f4, K4, expand( eData, 75 ) ); subRound( E, A, B, C, D, f4, K4, expand( eData, 76 ) ); subRound( D, E, A, B, C, f4, K4, expand( eData, 77 ) ); subRound( C, D, E, A, B, f4, K4, expand( eData, 78 ) ); subRound( B, C, D, E, A, f4, K4, expand( eData, 79 ) ); A += a0; B += b0; C += c0; D += d0; E += e0; return as_ulong((uint2)(D, E)); }
ããã§ããã€ãã®æ確åãå¿ èŠã§ãã ã¯ã©ãã¯ã®ããã®ãå®éšçãªããã¹ã¯ãŒãããã·ã¥ãšããŠãç§ã¯ãªãŒã¯ãããLinkedInããã·ã¥ãåããŸãããããã¯ã»ãŒ600äžïŒäžæïŒã§ãã ãªã¹ãå ã®ååšãããªãè¿ éã«ç¢ºèªããããã®ããã€ãã®ãªãã·ã§ã³ããããŸããããã·ã¥ããŒãã«ã䜿çšããŸããïŒè©³çŽ°ã¯åŸã»ã©ïŒã ã¡ã¢ãªæ¶è²»ãåæžããSHA1ã®20ãã€ãå šäœã§ã¯ãªããæåŸã®8ãã€ããã€ãŸã 1ã€ã®long / ulongå€ã ãã¡ãããããã¯èª€ã£ãäžèŽã®å¯èœæ§ãé«ããŸãããããã¯éåžžã«å°ãããŸãŸã§ããç§ãæã£ãŠãããã¹ãŠã®ãã¹ã¯ãŒãã®äžã§ãç§ã¯ãã®ãããªã±ãŒã¹ã6ã€ããæã£ãŠããŸããã§ããã ãããã£ãŠãåãæšãŠãããå€ïŒæåŸã®8ãã€ãïŒã¯ãäžèšã®é¢æ°ããããã«è¿ãããŸãã ãã以å€ã®å Žåããã¹ãŠãæšæºã§ãããSHA1ã¢ã«ãŽãªãºã ã¯ã56ãã€ãæªæºã®æååã®å Žåã®ä»æ§ã«åŸã£ãŠçŽæ¥å®è£ ãããŸãã
æ€çŽ¢ã®æ§æ
次ã«ãæ€çŽ¢èªäœãæŽçããå¿ èŠããããŸãã æãåçŽãªãªãã·ã§ã³ã¯ããã¹ãŠã®äœçœ®ã«å¯ŸããŠåãæåã»ããã®ãã«ãŒããã©ãŒã¹ã§ãããããã¯ãããšãã°åæ§ã®æ¹æ³ã§çŽæ¥å®è£ ã§ããŸãã
é衚瀺ã®ããã¹ã
__kernel void do_brute( __global const long *table, const ulong start_num, __global ulong *result, __global uint *res_ind) { char s[64]; uint *s_l = (__local uint *)s; int i, j; ulong _n, n; ulong start = start_num + get_global_id(0) * HASHES_PER_WORKITEM; for (j = 0; j < HASHES_PER_WORKITEM; j++) { n = _n = j + start; for (i = 15; i >= 0; i--) { s_l[i] = 0; } for (i = COMB_LEN - 1; i >= 0; i--) { s[i] = charset[n % CHARS_CNT]; n /= CHARS_CNT; } if (check_in_table(table, sha1(s_l, COMB_LEN))) { result[atomic_inc(res_ind)] = _n; } } }
ããã§ãHASHES_PER_WORKITEMã¯ã1åã®å®è¡ã§1ã€ã®äœæ¥é ç®ïŒã¹ããªãŒã ïŒã§åŠçãããããã·ã¥ã®æ°ãCOMB_LENã¯çµã¿åããã®é·ããcharsetã¯æåã®é åãCHARS_CNTã¯é åå ã®æåã®æ°ã§ãã ã芧ã®ãšãããèµ·åæã«ãããã·ã¥ããŒãã«ãžã®ãã€ã³ã¿ãŒãæ€çŽ¢ãéå§ãããã¹ã¯ãŒãçªå·ãããã³çµæã衚瀺ããé åãžã®ãã€ã³ã¿ãŒãšãã®äžã®ã€ã³ããã¯ã¹ããã®ã«ãŒãã«ã«æž¡ãããŸãã
OpenCLã§ã¯ãäžåºŠã«1ã€ã®ã¹ã¬ãããèµ·åãããããã§ã¯ãããŸãããããã®äžéšã¯ã°ããŒãã«ã¯ãŒã¯ãµã€ãºãšåŒã°ãããã¹ãŠã®ã¹ã¬ããã¯åãåŒæ°ãåãåããŸãã ãããã®ãããããããŒã¹ããŒã¹ã®äžéšãæŽçããããã«ãæåå
ulong start = start_num + get_global_id(0) * HASHES_PER_WORKITEM;
ç¹å®ã®ã¹ã¬ããã®çªå·ãèšç®ããŸãïŒget_global_idïŒ0ïŒã¯ã0ããçŸåšã®ã°ããŒãã«äœæ¥ãµã€ãºãŸã§ã®ã¹ã¬ããã€ã³ããã¯ã¹ãè¿ãæšæºé¢æ°ã§ãïŒã
次ã«ãåã¹ããªãŒã HASHES_PER_WORKITEMã¯ãã¹ã¯ãŒããåæããŸããåãã¹ã¯ãŒãã¯sha1é¢æ°ã«ãã£ãŠããã·ã¥åãããåŸè¿°ããcheck_in_tableé¢æ°ã®ååšã確èªããŸãã ãã®åœ¢åŒã§ãããã·ã¥ããŒãã«ã®æãåçŽãªå®è£ ã§ã¯ã1ç§ãããçŽ2,000äžã®ãã¹ã¯ãŒãã®çµæãåŸãããŸãããããšãã°ãã©ãããããã§3å以äžã®ããã·ã¥ãçæããoclHascatïŒæ€èšŒãå€æ°ã®ããã·ã¥ã®ãªã¹ããééããå Žåã§ãïŒãããæ£åœåãããã®ã§ã¯ãããŸããïŒã ä»åŸã¯ãåçŽãªãã«ãŒããã©ãŒã¹ã§1ç§éã«1å6,000äžã®é床ãéæã§ãããšèšããŸããããã¯oclHascatã®ååã®é床ïŒããã·ã¥1ã€ïŒã§ãã
ããã·ã¥ããŒãã«
ãã®ãããããã·ã¥ã®ååšã確èªããŸãã å®è£ ãããæåã®ãªãã·ã§ã³ã¯ã ãªãŒãã³ã¢ãã¬ã¹æå®ã®æãåçŽãªããã·ã¥ããŒãã«ã§ããã åé¡ãè€éã«ããªãããã«ãããã»ããµãšãããªã«ãŒãã§ã¯ãªããOpenCLã§ã¯ãèŠæ±ã®ã¿ããããŸããã ãã®ã±ãŒã¹ã¯æ¬¡ã®ããã«ãªããŸããã
é衚瀺ã®ããã¹ã
bool check_in_table( __global const long *table, const long value) { uint index = calc_index(value); uint step = calc_step(value); for (uint a = 1; ; a++) { index %= TABLE_SIZE; if (table[index] == 0) { return false; } if (table[index] == value) { return true; } index += a * step + 1; } }
ããŸããŸãªããŒãã«ãµã€ãºãšãããŒãæ¹æ³ãè©ŠããŸããããé床ã¯ããã»ã©åäžããŸããã§ããã GPUããã·ã¥ããŒãã«ã«é¢ããè³æãæ¢ããŠãç¹å®ã®Cuckoo Hashtable ïŒãã·ã¢èªãžã®ç¿»èš³ã確ç«ãããŠãããã©ããã¯ããããŸããïŒã«ã€ããŠèšåããŠããVasily Volkovã®èšäºãGPUã§ã®å¹ççãªããã·ã¥ããŒãã«ã®æ§ç¯ãã«åºäŒããŸãããèããªãã£ãã ç°¡åã«èšãã°ããã®æ¬è³ªã¯ã1ã€ã§ã¯ãªãããã€ãã®ããã·ã¥é¢æ°ã䜿çšããããšãšãç¹å¥ãªå¡ãã€ã¶ãæ¹æ³ã«ãããŸãããã®åŸãkå以äžã®ã¡ã¢ãªã¢ã¯ã»ã¹ã«å¯ŸããŠèŠçŽ ãèŠã€ãããŸããkã¯ããã·ã¥é¢æ°ã®æ°ã§ãã å æã¡ã¢ãªãããé床ãéèŠãªã®ã§ãk = 2ã䜿çšããŸããã ãããåããããšã¯CPUã§ãçºçããŸãã
ãããã«
ãŸãããã¡ãããæé©åã¯ã³ãŒãã®å¥ã®éšåãã€ãŸããã¹ã¯ãŒãã®çæã«åœ±é¿ããŸããã äžèšã®ããŒãžã§ã³ã§ã¯ãããã€ãã®æé©ã§ã¯ãªãå Žæãããã«è¡šç€ºãããŸããããšãã°ã次ã®åãã¹ã¯ãŒãã¯æåããçæãããŸãããåã®ãã®ã¯å€æŽã§ããŸãã ç¹ã«OpenCLã«åºæã®æé©åã«ã¯ä»ã®å ŽæããããŸãïŒããé«éãªããŒã«ã«ã®ä»£ããã«ãæåã®é åã«ã°ããŒãã«ã¡ã¢ãªãŸãã¯å®æ°ã¡ã¢ãªã䜿çšããŸãïŒç¹å®ã®å®è£ ã®éçºè ããçŽæ¥ã¡ã¢ãªé åã®è©³çŽ°ãèªãæ¹ãè¯ãã§ãïŒ ãã ããã«ãŒãã«ã³ãŒãã®ããŸããŸãªæé©åã«é¢ããåå¥ã®èšäºãæžã䟡å€ã¯ãããŸãããããã§ã¯ãGPUåãã®ããã°ã©ãã³ã°ãè¡ãå ŽåãããŸããŸãªãªãã·ã§ã³ãè©ŠããŠãã®é床ã調ã¹ã䟡å€ããããšèšããŸãã ç®ã§èšããšãåäœãéããªããšã¯éããŸããã ç¹å®ã®åœä»€ãåé€ããŠããå®è¡é床ãå€§å¹ ã«äœäžããå ŽåããããŸãã
å°æ¥çã«ã¯ãäœçœ®ããšã«ç°ãªãã¢ã«ãã¡ãããã®ãµããŒããè¿œå ããŸãããããã«éèŠãªããšã¯ãåã ã®æåã ãã§ãªããåèªã®ã¢ã«ãã¡ãããããµããŒãããããšã§ãã å©äŸ¿æ§ãšæè»æ§ã®ããã«ãã«ãŒãã«ã³ãŒãã¯Makoãã³ãã¬ãŒããšã³ãžã³ã«ãã£ãŠåŠçãããŸãã ãããã¯ãã¹ãŠã¢ãŒã«ã€ãã«ãããŸãïŒä»¥äžãåç §ïŒã
çµè«
ã ãããç§ãæçµçã«ååŸãããã®ïŒ
- å€ãã®åŸ®åŠãªç¹ãåããOpenCLã®ç¥èïŒæåãããããªãæåããŠãããšæããŸãïŒ
- Pythonã§ã®ããã°ã©ãã³ã°ã®ã¬ãã«ãäžããŸããïŒãŸã£ãããŒãããã§ã¯ãªããããªãäœãã¬ãã«ããïŒ
- é¢é£æè¡ãåŠã³ãè©ŠããŠã¿ãŸããïŒCythonã³ã³ãã€ã©ãŒãMakoãã³ãã¬ãŒããšã³ãžã³ãVCS git
æ圢ã®çµæïŒ
- ããã°ã©ã ã¯ãã©ããããããããªã«ãŒãã§åçŽãªãã«ãŒããã©ãŒã¹ïŒæåã§ã¯ãªãåèªã®ã¢ã«ãã¡ãããã䜿çšããå Žåãé床ã¯æ¯ç§5,000äžããïŒã®ããã«ãæ¯ç§çŽ1å6åäžã®é床ã§ãã¹ã¯ãŒããåæããŸã-äžæ¹ãoclHascatã§3åãšæ¯èŒã§ããŸã1ã€ã¯ããã·ã¥ããã1ã€ã¯CPUã®æéãã«ãŒããã©ãŒã¹ããã»ããµïŒi5 2.5 GHzãæèŒïŒã§3000äžåãã¢ã»ã³ãã©ãŒãšSSEåœä»€ã䜿çšããŠèšè¿°
- ããã䜿çšããŠãããªãã¯ãªãã§ãLinkedInããã·ã¥ããçŽ250äžã®ãã¹ã¯ãŒããéžæãããŸããïŒããŸãå€ãã¯ãããŸããããããã§ã¯èšé²ãç®æããŠããŸããã§ããïŒ
- ããããããŠã³ããŒãã§ããŸãïŒäžéšã®å Žæã«ã¯æãããç³ããããŸãïŒïŒãéå§ããã«ã¯ãPython 2.7ãnumpyãPyOpenCLãCythonãMakoãããã³LinkedInããã·ã¥ä»ãã®ãã¡ã€ã«ãå¿ èŠã§ãã
å°è±¡
- Pythonã¯éåžžã«é ãèšèªã§ããïŒæžãã®ã¯éåžžã«ç°¡åã§ãïŒãã«ãŒãã§å€§ããªãªã¹ããåŠçããã®ã¯éåžžã«é ããããŸããŸãªç解床ã§ãããããCythonãããã°ã©ã ã®äžéšã«äœ¿çšãããçç±ã§ã-ãšããã§ãæ¬åœã«äŸ¿å©ãªããš
- ãããã¡ã€ãªã³ã°ãšãã®åŸã®æé©åã«å¯Ÿããé©åãªã¢ãããŒããåããOpenCLã¯éåžžã«è¿ éã«æ©èœãããããã¢ã»ã³ãã©ãŒã§äœããæžãæããå¿ èŠã¯ãããŸããã
PSïŒ
ããŸããŸãªã³ã¡ã³ããæšå¥šäºé ãæè¿ããŸãã