Fast Image квадрат на (int) Image - неоновые встроенные ARM - iOS Dev - PullRequest
2 голосов
/ 17 января 2012

Может кто-нибудь сказать мне быструю функцию для нахождения квадрата каждого пикселя изображения int .Мне это нужно для iOS-приложения.Я работаю непосредственно с памятью изображения, определенного как

int *image_sqr_Baseaaddr = (int *) malloc(noOfPixels * sizeof(int));

for (int i=0; i<newNoOfPixels; i++)
     image_sqr_Baseaaddr[i] = (int) image_scaled_Baseaaddr[i] * (int) image_scaled_Baseaaddr[i];

Это, очевидно, самая медленная из возможных функций.Я слышал, что встроенные в iOS ARM Neon можно использовать для выполнения нескольких операций за 1 цикл.Может быть, это путь?

Проблема в том, что я не очень знаком и мне не хватает времени на изучение ассемблера.Поэтому было бы здорово, если бы кто-нибудь мог опубликовать встроенный код Neon для упомянутой выше проблемы или любую другую быструю реализацию на C / C ++.

Единственный код в встроенных NEON, который я могу найти в Интернете, - это коддля RGB в серый http://computer -vision-talks.com / 2011/02 / очень быстрое преобразование bgra-to-grayscale-на-iphone /

1 Ответ

3 голосов
/ 17 января 2012

Вот простая реализация NEON:

#include <arm_neon.h>

// ...

int i;

for (i = 0; i <= newNoOfPixels - 16; i += 16)           // SIMD loop
{
    uint8x16_t v = vld1q_u8(&image_scaled_Baseaaddr[i]);// load 16 x 8 bit pixels

    int16x8_t vl = (int16x8_t)vmovl_u8(vget_low_u8(v)); // unpack into 2 x 16 bit vectors
    int16x8_t vh = (int16x8_t)vmovl_u8(vget_high_u8(v));

    vl = vmulq_s16(vl, vl);                             // square them
    vh = vmulq_s16(vh, vh);

    int32x4_t vll = vmovl_s16(vget_low_s16(vl));        // unpack to 4 x 32 bit vectors
    int32x4_t vlh = vmovl_s16(vget_high_s16(vl));
    int32x4_t vhl = vmovl_s16(vget_low_s16(vh));
    int32x4_t vhh = vmovl_s16(vget_high_s16(vh));

    vst1q_s32(&image_sqr_Baseaaddr[i], vll);            // store 32 bit squared values
    vst1q_s32(&image_sqr_Baseaaddr[i + 4], vlh);
    vst1q_s32(&image_sqr_Baseaaddr[i + 8], vhl);
    vst1q_s32(&image_sqr_Baseaaddr[i + 12], vhh);
}
for ( ; i < newNoOfPixels; ++i)                         // scalar clean up loop
{
    int32_t p = (int32_t)image_scaled_Baseaaddr[i];
    image_sqr_Baseaaddr[i] = p * p;
}

Обратите внимание, что это будет работать лучше, если и image_scaled_Baseaaddr, и image_sqr_Baseaaddr выровнены по 16 байтов.

Обратите внимание, чтоприведенный выше код не протестирован и может потребовать дальнейшей работы.

...