内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用
为64维编写代码来说明这个问题:
// a has 64 elements. b is a bitvector of 64 dimensions. float dot(float *restrict a, uint64_t b) { float sum = 0; for(int i=0; b && i<64; i++, b>>=1) { if (b & 1) sum += a[i]; } return sum; }
可以:
movl $4660, %edx movl $5, %ecx xorps %xmm0, %xmm0 .p2align 4,,10 .p2align 3 .L4: testb $1, %cl je .L2 addss (%rdx), %xmm0 .L2: leaq 4(%rdx), %rax shrq %rcx testb $1, %cl je .L8 addss 4(%rdx), %xmm0 .L8: shrq %rcx testb $1, %cl je .L9 addss 4(%rax), %xmm0 .L9: shrq %rcx testb $1, %cl je .L10 addss 8(%rax), %xmm0 .L10: shrq %rcx testb $1, %cl je .L11 addss 12(%rax), %xmm0 .L11: shrq %rcx testb $1, %cl je .L12 addss 16(%rax), %xmm0 .L12: shrq %rcx testb $1, %cl je .L13 addss 20(%rax), %xmm0 .L13: shrq %rcx testb $1, %cl je .L14 addss 24(%rax), %xmm0 .L14: leaq 28(%rax), %rdx shrq %rcx cmpq $4916, %rdx jne .L4 ret
代码
/* Includes */ #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <smmintrin.h> /* SSE 4.1 */ #include <time.h> /* Defines */ #define ALIGNTO(n) __attribute__((aligned(n))) #define USE_PINSRW 1 #define NUM_ITERS 2260000 /** * Bit mask shuffle. * * This version uses a loop to store eight u16 and reloads them as one __m128i. */ __m128 bitMaskShuffleStoreAndReload(__m128i mask){ const __m128i perm ALIGNTO(16) = _mm_set_epi8(15, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 0); int i; uint16_t interMask[8] ALIGNTO(16); /* Shuffle bitmask */ /* Stage 1 */ for(i=7;i>=0;i--){ interMask[i] = _mm_movemask_epi8(mask); mask = _mm_slli_epi32(mask, 1); } /* Stage 2 */ return _mm_castsi128_ps( _mm_shuffle_epi8( _mm_load_si128((const __m128i*)interMask), perm) ); } /** * Bit mask shuffle. * * This version uses the PINSTRW instruction. */ __m128 bitMaskShufflePINSRW(__m128i mask){ const __m128i perm ALIGNTO(16) = _mm_set_epi8(15, 7, 14, 6, 13, 5, 12, 4, 11, 3, 10, 2, 9, 1, 8, 0); __m128i imask ALIGNTO(16); /* Shuffle bitmask */ /* Stage 1 */ imask = _mm_insert_epi16(imask, _mm_movemask_epi8(mask), 7); mask = _mm_slli_epi16(mask, 1); imask = _mm_insert_epi16(imask, _mm_movemask_epi8(mask), 6); mask = _mm_slli_epi16(mask, 1); imask = _mm_insert_epi16(imask, _mm_movemask_epi8(mask), 5); mask = _mm_slli_epi16(mask, 1); imask = _mm_insert_epi16(imask, _mm_movemask_epi8(mask), 4); mask = _mm_slli_epi16(mask, 1); imask = _mm_insert_epi16(imask, _mm_movemask_epi8(mask), 3); mask = _mm_slli_epi16(mask, 1); imask = _mm_insert_epi16(imask, _mm_movemask_epi8(mask), 2); mask = _mm_slli_epi16(mask, 1); imask = _mm_insert_epi16(imask, _mm_movemask_epi8(mask), 1); mask = _mm_slli_epi16(mask, 1); imask = _mm_insert_epi16(imask, _mm_movemask_epi8(mask), 0); /* Stage 2 */ return _mm_castsi128_ps( _mm_shuffle_epi8( imask, perm) ); } /** * SSE 4.1 implementation. */ float dotSSE41(__m128 f[32], unsigned char maskArg[16]){ int i, j, k; __m128i mask ALIGNTO(16) = _mm_load_si128((const __m128i*)maskArg); __m128 shufdMask ALIGNTO(16); __m128 zblended ALIGNTO(16); __m128 sums ALIGNTO(16) = _mm_setzero_ps(); float sumsf[4] ALIGNTO(16); /* Shuffle bitmask */ #if USE_PINSRW shufdMask = bitMaskShufflePINSRW(mask); #else shufdMask = bitMaskShuffleStoreAndReload(mask); #endif /* Dot product */ for(i=1;i>=0;i--){ for(j=1;j>=0;j--){ for(k=7;k>=0;k--){ zblended = _mm_setzero_ps(); zblended = _mm_blendv_ps(zblended, f[i*16+j+k*2], shufdMask); sums = _mm_add_ps(sums, zblended); shufdMask = _mm_castsi128_ps(_mm_slli_epi32(_mm_castps_si128(shufdMask), 1)); } } } /* Final Summation */ _mm_store_ps(sumsf, sums); return sumsf[0] + sumsf[1] + sumsf[2] + sumsf[3]; } /** * Reference C implementation */ float dotRefC(float f[128], unsigned char mask[16]){ float sum = 0.0; int i; for(i=0;i<128;i++){ sum += ((mask[i>>3]>>(i&7))&1) ? f[i] : 0.0; } return sum; } /** * Main */ int main(void){ /* Variables */ /* Loop Counter */ int i; /* Data to process */ float data[128] ALIGNTO(16); unsigned char mask[16] ALIGNTO(16); float refCSum, sseSum; /* Time tracking */ clock_t t1, t2, t3; double refCTime, sseTime; /* Initialize mask and float arrays with some random data. */ for(i=0;i<128;i++){ if(i<16) mask[i]=rand(); data[i] = random(); } /* RUN TESTS */ t1 = clock(); for(i=0;i<NUM_ITERS;i++){ refCSum = dotRefC(data, mask); } t2 = clock(); for(i=0;i<NUM_ITERS;i++){ sseSum = dotSSE41((__m128*)data, mask); } t3 = clock(); /* Compute time taken */ refCTime = (double)(t2-t1)/CLOCKS_PER_SEC; sseTime = (double)(t3-t2)/CLOCKS_PER_SEC; /* Print out results */ printf("Results:\n" "RefC: Time: %f Value: %f\n" "SSE: Time: %f Value: %f\n", refCTime, refCSum, sseTime, sseSum); return 0; }
在掩码中,128位
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
由8个PMOVMASKB和8个PSLLW指令排列,第一个指令为
0 8 16 24 32 40 48 56 64 72 80 88 96 104 112 120 1 9 17 25 33 41 49 57 65 73 81 89 97 105 113 121 2 10 18 26 34 42 50 58 66 74 82 90 98 106 114 122 3 11 19 27 35 43 51 59 67 75 83 91 99 107 115 123 4 12 20 28 36 44 52 60 68 76 84 92 100 108 116 124 5 13 21 29 37 45 53 61 69 77 85 93 101 109 117 125 6 14 22 30 38 46 54 62 70 78 86 94 102 110 118 126 7 15 23 31 39 47 55 63 71 79 87 95 103 111 119 127
通过一个PSHUFB指令
0 8 16 24 32 40 48 56 4 12 20 28 36 44 52 60 64 72 80 88 96 104 112 120 68 76 84 92 100 108 116 124 1 9 17 25 33 41 49 57 5 13 21 29 37 45 53 61 65 73 81 89 97 105 113 121 69 77 85 93 101 109 117 125 2 10 18 26 34 42 50 58 6 14 22 30 38 46 54 62 66 74 82 90 98 106 114 122 70 78 86 94 102 110 118 126 3 11 19 27 35 43 51 59 7 15 23 31 39 47 55 63 67 75 83 91 99 107 115 123 71 79 87 95 103 111 119 127
目前呼叫中心只有API文档,需要用户自己开发。如果用户需要saas系统的呼叫中心可以使用智能外呼机器人:https://cloud.tencent.com/product/ccsr
你有没有调整观众端表现,即通过对 LivePushConfig 中的homeOrientation设置项进行配置,它控制的是观众端看到的视频宽高比是16:9还是6:19,调整后的结果可以用播放器查看以确认是否符合预期。
控制台使用的是新的接口,批量创建子网,https://cloud.tencent.com/document/product/215/31960,可以指定路由表。terraform开发的时候是基于api2.0开发的,还没有这个接口,因此暂时无法使用