вращение битовых массивов. В коде

Чтобы решить эту проблему, вам нужно внести изменения в пакет response-native-navigation. Откройте файл NavigationActivity.java и замените следующий код на новый:

Замените этот код:

@Override
    public void invokeDefaultOnBackPressed() {
        if (!navigator.handleBack(new CommandListenerAdapter())) {
         super.onBackPressed();
        }
    }

На этот:

@Override
    public void invokeDefaultOnBackPressed() {
        if (!navigator.handleBack(new CommandListenerAdapter())) {
          this.moveTaskToBack(true);
         //super.onBackPressed();
        }
    }

После сохранения изменений проверьте на устройстве Android.

18
задан Marco van de Voort 9 November 2016 в 17:54
поделиться

4 ответа

Да, есть более быстрые способы сделать это.

Ваш простой цикл большую часть времени тратит на промахи в кэше. Это происходит потому, что вы касаетесь большого количества данных в самых разных местах в замкнутом цикле. Еще хуже: ваши ячейки памяти разделены на две степени. Это размер, при котором кэш работает хуже всего.

Вы можете улучшить этот алгоритм ротации, если улучшите локальность доступа к памяти.

Простой способ сделать это - повернуть каждый блок размером 8x8 пикселей самостоятельно, используя тот же код, который вы использовали для всего растрового изображения, и обернуть другой цикл, который разбивает поворот изображения на фрагменты размером 8x8 пикселей каждый.

Например, что-то вроде этого (не проверено и извините за C-код. Мои навыки Delphi не обновлены):

 // this is the outer-loop that breaks your image rotation
 // into chunks of 8x8 pixels each:
 for (int block_x = 0; block_x < 2048; block_x+=8)
 {
    for (int block_y = 0; blocky_y < 2048; block_y+=8)
    { 
       // this is the inner-loop that processes a block
       // of 8x8 pixels.
       for (int x= 0; x<8; x++)
         for (int y=0; y<8; y++)
            dest[x+block_x][y+block_y] = src[y+block_y][x+block_x]
    }
 } 

Есть и другие способы. Вы можете обрабатывать данные в порядке Гильберта или Мортона. Теоретически это было бы даже немного быстрее, но код будет намного сложнее.

Btw - Поскольку вы упомянули, что SSE - это вариант для вас. Обратите внимание, что вы можете вращать блок размером 8x8 байтов в регистрах SSE. Это немного сложно заставить его работать, но просмотр кода транспонирования матрицы SSE должен помочь вам начать, поскольку это одно и то же.


РЕДАКТИРОВАТЬ:

Только что проверено:

При размере блока 8x8 пикселей код работает ок. На моей машине в 5 раз быстрее. При размере блока 16x16 он работает в 10 раз быстрее.

Похоже, это хорошая идея поэкспериментировать с разными размерами блоков.

Вот (очень простая) тестовая программа, которую я использовал:

#include <stdio.h>
#include <windows.h>

char temp1[2048*2048];
char temp2[2048*2048];

void rotate1 (void)
{
  int x,y;
  for (y=0; y<2048; y++)
  for (x=0; x<2048; x++)
    temp2[2048*y+x] = temp1[2048*x+y];
}

void rotate2 (void)
{
  int x,y;
  int bx, by;

  for (by=0; by<2048; by+=8)
  for (bx=0; bx<2048; bx+=8)
  for (y=0; y<8; y++)
  for (x=0; x<8; x++)
    temp2[2048*(y+by)+x+bx] = temp1[2048*(x+bx)+y+by];
}

void rotate3 (void)
{
  int x,y;
  int bx, by;

  for (by=0; by<2048; by+=16)
  for (bx=0; bx<2048; bx+=16)
  for (y=0; y<16; y++)
  for (x=0; x<16; x++)
    temp2[2048*(y+by)+x+bx] = temp1[2048*(x+bx)+y+by];
}


int main (int argc, char **args)
{
  int i, t1;

  t1 = GetTickCount();
  for (i=0; i<20; i++) rotate1();
  printf ("%d\n", GetTickCount()-t1);

  t1 = GetTickCount();
  for (i=0; i<20; i++) rotate2();
  printf ("%d\n", GetTickCount()-t1);

  t1 = GetTickCount();
  for (i=0; i<20; i++) rotate3();
  printf ("%d\n", GetTickCount()-t1);

}
]
21
ответ дан 30 November 2019 в 08:38
поделиться

Если вы умеете использовать C ++, то можете посмотреть Eigen .

Это библиотека шаблонов C ++, которая использует SSE (2 и более поздние версии) и наборы инструкций AltiVec с плавным откатом к невекторизованному коду .

Быстро. (См. Тест).
Шаблоны выражений позволяют разумно удалять временные объекты и включать ленивую оценку, когда это уместно - Eigen заботится об этом автоматически и в большинстве случаев обрабатывает псевдонимы.
Явная векторизация выполняется для наборов инструкций SSE (2 и новее) и AltiVec с постепенным откатом к невекторизованному коду. Шаблоны выражений позволяют выполнять эту оптимизацию глобально для целых выражений.
С объектами фиксированного размера избегается динамическое выделение памяти, и циклы разворачиваются, когда это имеет смысл.
Для больших матриц особое внимание уделяется удобству кеширования.

3
ответ дан 30 November 2019 в 08:38
поделиться

Вы могли улучшить его, копируя блоки, выровненные по кешу, а не по строкам, так как в данный момент шаг любого src dest будет ошибочным ( в зависимости от того, является ли delphi основной строкой или основным столбцом).

0
ответ дан 30 November 2019 в 08:38
поделиться

Если изображение не квадратное, вы не можете работать на месте. Даже если вы работаете с квадратными изображениями, преобразование не способствует работе на месте.

Если вы хотите попытаться сделать что-то немного быстрее, вы можете попробовать воспользоваться шагами строк, чтобы заставить его работать, но я думаю, что лучшее, что вы могли бы сделать, - это прочитать 4 байта за раз из источника, а затем записать его в четыре последовательные строки в dest. Это должно сократить ваши накладные расходы, но я бы не ожидал улучшения более чем на 5%.

0
ответ дан 30 November 2019 в 08:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: