Действительно, комментарии верны: компилятор может сделать для вас векторизацию. Я немного изменил ваш код для улучшения авто-векторизации. В gcc -O3 -march=haswell -std=c++14
(gcc версии 8.2) следующий код:
#include
#include
void cvt_uint8_int16(uint16_t * __restrict__ canvas, uint8_t * __restrict__ addon, int64_t count) {
int64_t i;
/* If you know that n is always a multiple of 32 then insert */
/* n = n & 0xFFFFFFFFFFFFFFE0u; */
/* This leads to cleaner code. Now assume n is a multiple of 32: */
count = count & 0xFFFFFFFFFFFFFFE0u;
for (i = 0; i < count; i++){
canvas[i] += static_cast(addon[i]);
}
}
компилируется в:
cvt_uint8_int16(unsigned short*, unsigned char*, long):
and rdx, -32
jle .L5
add rdx, rsi
.L3:
vmovdqu ymm2, YMMWORD PTR [rsi]
add rsi, 32
add rdi, 64
vextracti128 xmm1, ymm2, 0x1
vpmovzxbw ymm0, xmm2
vpaddw ymm0, ymm0, YMMWORD PTR [rdi-64]
vpmovzxbw ymm1, xmm1
vpaddw ymm1, ymm1, YMMWORD PTR [rdi-32]
vmovdqu YMMWORD PTR [rdi-64], ymm0
vmovdqu YMMWORD PTR [rdi-32], ymm1
cmp rdx, rsi
jne .L3
vzeroupper
.L5:
Компилятор Clang создает код , который немного отличается : Он загружает 128-битные (char) векторы и конвертирует их с помощью vpmovzxbw
. Компилятор gcc загружает 256-битные (char) векторы и преобразует верхний и нижний 128-битные по отдельности, что, вероятно, немного менее эффективно. Тем не менее, ваша проблема, скорее всего, ограничена пропускной способностью (так как длина> 1000000).
Вы также можете векторизовать код с помощью встроенных функций (не проверено):
void cvt_uint8_int16_with_intrinsics(uint16_t * __restrict__ canvas, uint8_t * __restrict__ addon, int64_t count) {
int64_t i;
/* Assume n is a multiple of 16 */
for (i = 0; i < count; i=i+16){
__m128i x = _mm_loadu_si128((__m128i*)&addon[i]);
__m256i y = _mm256_loadu_si256((__m256i*)&canvas[i]);
__m256i x_u16 = _mm256_cvtepu8_epi16(x);
__m256i sum = _mm256_add_epi16(y, x_u16);
_mm256_storeu_si256((__m256i*)&canvas[i], sum);
}
}
Это приводит к аналогичным результатам , что и векторизованный код.
Можно сделать это, это - определенная работа все же.
На сервисной стороне необходимо будет создать собственное ServiceHost
и переопределение ApplyConfiguration
метод.
Проверьте это сообщение в блоге
На стороне клиента Вы делаете что-то подобное, но обеспечиваете пользовательское ChannelFactory
и переопределение ApplyConfiguration
метод там.