Возможная фрагментация памяти ARM Linux с NEON Copy, но без memcpy

c++ linux arm memcpy neon

145 просмотра

1 ответ

Я использую Linux 4.4 на плате BeagleBone X-15 (ARM Cortex-A15). Мое приложение отображает выходные данные графического процессора SGX и должно скопировать резервное хранилище DRM.

И memcpy, и мой пользовательский код копирования NEON работают ... но код NEON работает намного быстрее (~ 11 мс против ~ 35 мс).

Я замечаю, что довольно часто после 12500 секунд, когда я использую версию копии NEON, Linux убивает приложение из-за нехватки памяти (OOM). Когда я запускаю приложение и изменяю одну строку с NEON copy на стандартную memcpy, оно работает бесконечно (пока 12 часов ...). Но копировать медленнее.

Я вставил код mmap, copy и NEON copy ниже. Что-то действительно не так с моей копией NEON? Спасибо.

Неоновая копия:

/**
* CompOpenGL neonCopyRGBAtoRGBA()
* Purpose: neonCopyRGBAtoRGBA - Software NEON copy
*
* @param src - Source buffer
* @param dst - Destination buffer
* @param numpix - Number of pixels to convert
*/
__attribute__((noinline)) void CompOpenGL::neonCopyRGBAtoRGBA(unsigned char* src, unsigned char* dst, int numPix)
{

    (void)src;
    (void)dst;
    (void)numPix;

    // This case takes RGBA -> BGRA
    __asm__ volatile(
                "mov r3, r3, lsr #3\n"           /* Divide number of pixels by 8 because we process them 8 at a time */
                "loopRGBACopy:\n"
                "vld4.8 {d0-d3}, [r1]!\n"        /* Load 8 pixels into d0 through d2. d0 = R[0-7], d1 = G[0-7], d2 = B[0-7], d3 = A[0-7] */
                "subs r3, r3, #1\n"              /* Decrement the loop counter */
                "vst4.8 {d0-d3}, [r2]!\n"        /* Store the RGBA into destination 8 pixels at a time */
                "bgt loopRGBACopy\n"
                "bx lr\n"
                );

}

Mmap и скопируйте код здесь:

union gbm_bo_handle handleUnion = gbm_bo_get_handle(m_Fb->bo);
struct drm_omap_gem_info gemInfo;
char *gpuMmapFrame = NULL;
gemInfo.handle = handleUnion.s32;
int ret = drmCommandWriteRead(m_DRMController->m_Fd, DRM_OMAP_GEM_INFO,&gemInfo, sizeof(gemInfo));
if (ret) {
    qDebug() << "Cannot set write/read";
}
else {
    // Mmap the frame
    gpuMmapFrame = (char *)mmap(0, gemInfo.size, PROT_READ | PROT_WRITE, MAP_SHARED,m_DRMController->m_Fd, gemInfo.offset);

    if ( gpuMmapFrame != MAP_FAILED ) {

        QElapsedTimer timer;
        timer.restart();

        //m_OGLController->neonCopyRGBAtoRGBA((uchar*)gpuMmapFrame,  (uchar*)m_cpyFrame,dmaBuf.width * dmaBuf.height);
        memcpy(m_cpyFrame,gpuMmapFrame,dmaBuf.height * dmaBuf.width * 4);

        qDebug() << "Copy Performance: " << timer.elapsed();
Автор: PhilBot Источник Размещён: 26.07.2019 01:44

Ответы (1)


1 плюс

Решение

Хорошей новостью является то, что ваша функция будет работать значительно быстрее, если вы замените vld4/vst4на vld1/vst1.

Плохая новость заключается в том, что вы должны сообщать, какие регистры вы используете и изменяете, включая CPSRи память, и вы не должны возвращаться из встроенной сборки. ( bx lr).

__asm__ volatile(
                "mov r3, r3, lsr #3\n"           /* Divide number of pixels by 8 because we process them 8 at a time */
                "loopRGBACopy:\n"
                "vld1.8 {d0-d3}, [r1]!\n"        /* Load 8 pixels into d0 through d2. d0 = R[0-7], d1 = G[0-7], d2 = B[0-7], d3 = A[0-7] */
                "subs r3, r3, #1\n"              /* Decrement the loop counter */
                "vst1.8 {d0-d3}, [r2]!\n"        /* Store the RGBA into destination 8 pixels at a time */
                "bgt loopRGBACopy\n"
                ::: "r1", "r2", "r3", "d0", "d1", "d2", "d3", "cc", "memory"
                );

http://www.ethernut.de/en/documents/arm-inline-asm.html

Автор: Jake 'Alquimista' LEE Размещён: 11.04.2018 06:09
Вопросы из категории :
32x32