Автор Тема: Мы победили :-)  (Прочитано 35431 раз)

Губанов Сергей Юрьевич

  • Hero Member
  • *****
  • Сообщений: 590
    • Просмотр профиля
    • Домашняя страница
Re: Мы победили :-)
« Ответ #60 : Апрель 23, 2013, 02:10:05 pm »
2) Почему то в твоем эксперименте получилась не линейная зависимость времени от N (числа проходов), а квадратичная (то есть вместо O(N) имеем O(N^2)). Это весьма странно.
Таймер не сбрасывается. Надо перед timer.Start(); указать timer.Reset();

Точно, таймер не сбрасывается!

Итак, правильные результаты:

N=1, t=0.003471 seconds
N=2, t=0.0322118 seconds
N=3, t=0.009048 seconds
N=4, t=0.0119841 seconds
N=5, t=0.0149944 seconds
N=6, t=0.0179927 seconds
N=7, t=0.0210585 seconds
N=8, t=0.0256923 seconds
N=9, t=0.0274187 seconds
N=10, t=0.0306925 seconds
N=11, t=0.0347208 seconds
N=12, t=0.0362271 seconds
N=13, t=0.0395649 seconds
N=14, t=0.0422456 seconds
N=15, t=0.0448891 seconds
N=16, t=0.0485976 seconds
N=17, t=0.0517676 seconds
N=18, t=0.0574415 seconds
N=19, t=0.0571965 seconds
N=20, t=0.0606412 seconds

То есть при N=20 получаем 16.5 FPS (или 5.5 FPS если делать это для трёх каналов в однопоточной программе).

Требуемых 30 FPS всё равно не получилось.

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Мы победили :-)
« Ответ #61 : Апрель 23, 2013, 02:32:03 pm »
2) Почему то в твоем эксперименте получилась не линейная зависимость времени от N (числа проходов), а квадратичная (то есть вместо O(N) имеем O(N^2)). Это весьма странно.
Таймер не сбрасывается. Надо перед timer.Start(); указать timer.Reset();

Точно, таймер не сбрасывается!

Итак, правильные результаты:

N=1, t=0.003471 seconds
N=2, t=0.0322118 seconds
N=3, t=0.009048 seconds
N=4, t=0.0119841 seconds
N=5, t=0.0149944 seconds
N=6, t=0.0179927 seconds
N=7, t=0.0210585 seconds
N=8, t=0.0256923 seconds
N=9, t=0.0274187 seconds
N=10, t=0.0306925 seconds
N=11, t=0.0347208 seconds
N=12, t=0.0362271 seconds
N=13, t=0.0395649 seconds
N=14, t=0.0422456 seconds
N=15, t=0.0448891 seconds
N=16, t=0.0485976 seconds
N=17, t=0.0517676 seconds
N=18, t=0.0574415 seconds
N=19, t=0.0571965 seconds
N=20, t=0.0606412 seconds

То есть при N=20 получаем 16.5 FPS (или 5.5 FPS если делать это для трёх каналов в однопоточной программе).

Требуемых 30 FPS всё равно не получилось.
Тут возможны еще несколько нюансов которые могут как-то влиять на производительность:
1) на самом деле при N=13 тоже размытие может быть вполне вменяемым. Так что пусть N=13.
2) У нас не двумерный, а одномерный массив на входе (в котором у нас r,g,b сразу).
3) Мы все же писали на C++, это может дать прирост производительности. Кроме того, нужно проверять не в Debug-сборке.
Y = λf.(λx.f (x x)) (λx.f (x x))

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Мы победили :-)
« Ответ #62 : Апрель 23, 2013, 02:35:23 pm »
2) У нас не двумерный, а одномерный массив на входе (в котором у нас r,g,b сразу).
нужно проверять не в Debug-сборке.
Еще точнее - у нас просто указатель на область памяти. Соответственно при каждом обращении нет никаких проверок на выход за границы массива.
Y = λf.(λx.f (x x)) (λx.f (x x))

DddIzer

  • Гость
Re: Мы победили :-)
« Ответ #63 : Апрель 23, 2013, 04:28:39 pm »
Прямо сейчас ничего не сниму и не выложу - не до того.
и не надо.. важно понять , для чего это делается - для подбора адекватной модели очистки того, что попало в фокус.. по херне которой вы скормили журналюгам  и участникам конкурса (и на которую вы дали ссылки) это не сделаешь...  ;)

DddIzer

  • Гость
Re: Мы победили :-)
« Ответ #64 : Апрель 23, 2013, 04:39:13 pm »
Я вот не пойму -- а нафига ваще этот блур? взять просто равномерный фон и на него наложить изображение человека. Ну или на фотку какую-нить. И не надо мучиться с блуром...
Затем, чтобы выглядело естественно. На краях всегда будут артефакты перехода, в случае блюра их можно естественным образом скрыть. Вообще, для данной задачи заменять "задний план" какой-то кратинкой - очень плохая идея. Предлагаю подумать например о волосах.

Короче, задача сводится к алгоритму выделения краёв силуэта человека/людей...
Нет, не сводится.
но тем не менее такой подход имеет право на жизнь и существует.. в видеорегистраторах (напр. VideoNET) - он не требует специальных камер с захватом глубины... при этом подходе  обьект фиксируется по небольшому движению - (например , покачиванию головы) - а дальше идет его удержание и регистрация эволюции (изменений ) со временем..- недостаток подхода.. окружение должно  быть статичным....

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Мы победили :-)
« Ответ #65 : Апрель 23, 2013, 04:42:10 pm »
Прямо сейчас ничего не сниму и не выложу - не до того.
и не надо.. важно понять , для чего это делается - для подбора адекватной модели очистки того, что попало в фокус.. по херне которой вы скормили журналюгам  и участникам конкурса (и на которую вы дали ссылки) это не сделаешь...  ;)

Для подбора адекватной модели не достаточно того что ты попросил. Нужно одновременно иметь depth-картинку и color-картинку. Причем depth нельзя выкладывать в виде видео (или в виде какого-нибудь png), ибо в видео не видно процентов 70 информации что в depth содержится. Также это все нельзя жать любыми видеокодеками что жмут с потерями (h263, h264 и так далее).
Y = λf.(λx.f (x x)) (λx.f (x x))

DddIzer

  • Гость
Re: Мы победили :-)
« Ответ #66 : Апрель 23, 2013, 04:49:53 pm »
Прямо сейчас ничего не сниму и не выложу - не до того.
и не надо.. важно понять , для чего это делается - для подбора адекватной модели очистки того, что попало в фокус.. по херне которой вы скормили журналюгам  и участникам конкурса (и на которую вы дали ссылки) это не сделаешь...  ;)

Для подбора адекватной модели не достаточно того что ты попросил. Нужно одновременно иметь depth-картинку и color-картинку
а я и не говорил, что этого достаточно  :D - просто по тому что вы дали вообще ничего не скажешь.. так поиграться только...

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Мы победили :-)
« Ответ #67 : Апрель 23, 2013, 04:55:29 pm »
а я и не говорил, что этого достаточно  :D - просто по тому что вы дали вообще ничего не скажешь.. так поиграться только...
Ну, дык, продухт же! Точнее прототип оного. Показывает конечный результат, по которому юзер и оцениват нужно оно ему или не нужно. Кстати, народ на хакатоне подходил, игрался живьем с нашей прогой.

Вообще, по хорошему, у PerC SDK есть свой формат записи "видео", где сохраняется действительно всё. Затем это файло можно через этот же PerC SDK считать и пробовать как-то обработать. Может быть полезно тем, у кого нет камеры, а повозиться хочется. Могу наснимать таких вот "видео" и выложить куда-то.

PS. PerC SDK API доступен для C++ и C#. Естественно только под винду. Винда нужна не старее Win7 SP1.
Y = λf.(λx.f (x x)) (λx.f (x x))

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Мы победили :-)
« Ответ #68 : Апрель 23, 2013, 05:13:41 pm »
Возможно кто-то даже научится со всем этим работать на Обероне, или там на КП в ББ, и заткнет нас, и других конкурсантов (уже большого конкурса Intel) за пояс, на деле доказав, что КП/ББ для подобных задач действительно дает преимущество в плане скорости и качества разработки, и правильные циклы таки рулят :-)

PS. Большой конкурс Интела это вот это: http://perceptualchallenge.intel.com ну и описалово на хабре: http://habrahabr.ru/company/intel/blog/166759/
Y = λf.(λx.f (x x)) (λx.f (x x))

Губанов Сергей Юрьевич

  • Hero Member
  • *****
  • Сообщений: 590
    • Просмотр профиля
    • Домашняя страница
Re: Мы победили :-)
« Ответ #69 : Апрель 24, 2013, 09:31:29 am »
Еще точнее - у нас просто указатель на область памяти. Соответственно при каждом обращении нет никаких проверок на выход за границы массива.

Перешёл в unsafe C# и убрал проверку индексов массивов. Ускорилось почти в 3 раза. В однопоточной RGB FPS = 30 при N = 10 (R = 20).

N = 1 (R = 2), dt=0.0017206 seconds, FPS = 581 (RGB FPS = 193)
N = 2 (R = 4), dt=0.0024114 seconds, FPS = 414 (RGB FPS = 138)
N = 3 (R = 6), dt=0.0032783 seconds, FPS = 305 (RGB FPS = 101)
N = 4 (R = 8 ), dt=0.0047132 seconds, FPS = 212 (RGB FPS = 70)
N = 5 (R = 10), dt=0.0055715 seconds, FPS = 179 (RGB FPS = 59)
N = 6 (R = 12), dt=0.006789 seconds, FPS = 147 (RGB FPS = 49)
N = 7 (R = 14), dt=0.0080567 seconds, FPS = 124 (RGB FPS = 41)
N = 8 (R = 16), dt=0.009428 seconds, FPS = 106 (RGB FPS = 35)
N = 9 (R = 18), dt=0.0100056 seconds, FPS = 99 (RGB FPS = 33)
N = 10 (R = 20), dt=0.0109701 seconds, FPS = 91 (RGB FPS = 30)
N = 11 (R = 22), dt=0.0120318 seconds, FPS = 83 (RGB FPS = 27)
N = 12 (R = 24), dt=0.0131353 seconds, FPS = 76 (RGB FPS = 25)
N = 13 (R = 26), dt=0.0149416 seconds, FPS = 66 (RGB FPS = 22)
N = 14 (R = 28), dt=0.0156479 seconds, FPS = 63 (RGB FPS = 21)
N = 15 (R = 30), dt=0.0164521 seconds, FPS = 60 (RGB FPS = 20)
N = 16 (R = 32), dt=0.0175388 seconds, FPS = 57 (RGB FPS = 19)
N = 17 (R = 34), dt=0.0185114 seconds, FPS = 54 (RGB FPS = 18)
N = 18 (R = 36), dt=0.0286554 seconds, FPS = 34 (RGB FPS = 11)
N = 19 (R = 38), dt=0.020801 seconds, FPS = 48 (RGB FPS = 16)
N = 20 (R = 40), dt=0.0218066 seconds, FPS = 45 (RGB FPS = 15)

namespace ConsoleApplication67
{
class Program
{
static unsafe void Main (string[] args)
{
const int H = 480;
const int W = 640;
double[] a = new double[H * W];
double[] b = new double[H * W];

System.Random r = new System.Random();
System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
for (int N = 1; N < 21; N++)
{
fixed (double* pa = &a[0])
{
for (int y = 0; y < H; y++)
{
for (int x = 0; x < W; x++)
{
*(pa + H *y + x) = r.Next();
}
}
}
timer.Reset();
timer.Start();
fixed (double* pa = &a[0])
{
fixed (double* pb = &b[0])
{
for (int n = 0; n < N; n++)
{
for (int y = 1; y < H-1; y++)
{
for (int x = 1; x < W-1; x++)
{
*(pb + H * y + x) = 0.25 * (*(pa + H * (y - 1) + x)
+ *(pa + H * (y + 1) + x)
+ *(pa + H * y + x - 1)
+ *(pa + H * y + x + 1));
}
}
for (int y = 1; y < H-1; y++)
{
for (int x = 1; x < W-1; x++)
{
*(pa + H * y + x) = 0.25 * (*(pb + H * (y - 1) + x)
+ *(pb + H * (y + 1) + x)
+ *(pb + H * y + x - 1)
+ *(pb + H * y + x + 1));
}
}
}
}
}
timer.Stop();
double dt = timer.Elapsed.TotalSeconds;
System.Console.WriteLine("N = {0} (R = {1}), dt={2} seconds, FPS = {3} (RGB FPS = {4})",
N, 2*N, dt, (int)(1.0/dt), (int)(1.0/(3*dt)));
}
System.Console.ReadLine();
}
}
}

Губанов Сергей Юрьевич

  • Hero Member
  • *****
  • Сообщений: 590
    • Просмотр профиля
    • Домашняя страница
Re: Мы победили :-)
« Ответ #70 : Апрель 24, 2013, 09:44:20 am »
Кстати если из цветового пространства RGB перейти в цветовое пространство навроде Lab, то сильно размыть достаточно будет только один канал L. Каналы a и b можно размыть немножко или не трогать вообще. Потом перейти обратно в RGB. Правда в настоящий Lab переводится дорого (там формулы нелинейные), а в "облегченный" (например тупо разностный: L = G, a = G - R, b = G - B) - конечный результат может не понравится по цветам, хотя для вебкамеры наверное сойдёт.

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Мы победили :-)
« Ответ #71 : Апрель 24, 2013, 10:35:36 am »
Еще точнее - у нас просто указатель на область памяти. Соответственно при каждом обращении нет никаких проверок на выход за границы массива.

Перешёл в unsafe C# и убрал проверку индексов массивов. Ускорилось почти в 3 раза. В однопоточной RGB FPS = 30 при N = 10 (R = 20).

N = 1 (R = 2), dt=0.0017206 seconds, FPS = 581 (RGB FPS = 193)
N = 2 (R = 4), dt=0.0024114 seconds, FPS = 414 (RGB FPS = 138)
N = 3 (R = 6), dt=0.0032783 seconds, FPS = 305 (RGB FPS = 101)
N = 4 (R = 8 ), dt=0.0047132 seconds, FPS = 212 (RGB FPS = 70)
N = 5 (R = 10), dt=0.0055715 seconds, FPS = 179 (RGB FPS = 59)
N = 6 (R = 12), dt=0.006789 seconds, FPS = 147 (RGB FPS = 49)
N = 7 (R = 14), dt=0.0080567 seconds, FPS = 124 (RGB FPS = 41)
N = 8 (R = 16), dt=0.009428 seconds, FPS = 106 (RGB FPS = 35)
N = 9 (R = 18), dt=0.0100056 seconds, FPS = 99 (RGB FPS = 33)
N = 10 (R = 20), dt=0.0109701 seconds, FPS = 91 (RGB FPS = 30)
N = 11 (R = 22), dt=0.0120318 seconds, FPS = 83 (RGB FPS = 27)
N = 12 (R = 24), dt=0.0131353 seconds, FPS = 76 (RGB FPS = 25)
N = 13 (R = 26), dt=0.0149416 seconds, FPS = 66 (RGB FPS = 22)
N = 14 (R = 28), dt=0.0156479 seconds, FPS = 63 (RGB FPS = 21)
N = 15 (R = 30), dt=0.0164521 seconds, FPS = 60 (RGB FPS = 20)
N = 16 (R = 32), dt=0.0175388 seconds, FPS = 57 (RGB FPS = 19)
N = 17 (R = 34), dt=0.0185114 seconds, FPS = 54 (RGB FPS = 18)
N = 18 (R = 36), dt=0.0286554 seconds, FPS = 34 (RGB FPS = 11)
N = 19 (R = 38), dt=0.020801 seconds, FPS = 48 (RGB FPS = 16)
N = 20 (R = 40), dt=0.0218066 seconds, FPS = 45 (RGB FPS = 15)
Угу. Это уже похоже на ту производительность, которую мы в конце концов получили в ту субботу (ну может раза в два медленней у тебя пока, надо будет проверить).

Отключение проверок границ массивов (переход на указатели в случае C#) и переход на unsafe ускоряет приложение в разы. Похоже в debug-версии C++ в MSVS тоже проверяются и границы массивов и вообще оно все такое safe, ибо переход на релиз-версию нам тоже дало прибавку производительности в 3 раза примерно.

Еще нюанс - ты тут экономишь на конвертации из double в byte (то есть по просту не конвертируешь, изображения тут у тебя сразу в double). В некоторых случаях это довольно дорогостоящая конвертация.
Y = λf.(λx.f (x x)) (λx.f (x x))

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Мы победили :-)
« Ответ #72 : Апрель 24, 2013, 10:54:07 am »
Кстати если из цветового пространства RGB перейти в цветовое пространство навроде Lab, то сильно размыть достаточно будет только один канал L. Каналы a и b можно размыть немножко или не трогать вообще. Потом перейти обратно в RGB. Правда в настоящий Lab переводится дорого (там формулы нелинейные), а в "облегченный" (например тупо разностный: L = G, a = G - R, b = G - B) - конечный результат может не понравится по цветам, хотя для вебкамеры наверное сойдёт.

Я тогда думал о работе в YUV, но решил что на допил уйдет слишком много времени, поэтому остались на RGB.
Y = λf.(λx.f (x x)) (λx.f (x x))

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Мы победили :-)
« Ответ #73 : Апрель 24, 2013, 12:39:26 pm »
Я тут немного поисследовал. В общем, во-первых я переписал последний вариант Сергея на полноценный RGB и байтовыми буферами. Также N я фиксировал (N=13), но зато тест идет не по одному кадру, а по 1000 кадрам (соответственно замеряем время для 1000 кадров - так точнее, и так реалистичнее (от длительного нагрева проц. может снизить частоту)).

Во-вторых я реализовал алгоритм Сергея на С++, чтобы можно было сравнить производительность собственно языков.

В-третьих я из нашего прототипа вытащил алгоритм размытия в отдельный проект. И замерял производительность именно этого алгоритма (а не всего pipeline'а, как раньше).

Итак, вначале результаты. Напомню, что радиус размытия (N) = 13. Обрабатываются все три канала. Число обрабатываемых кадров = 1000.
C# (алгоритм Cергея):
   time: 107 seconds
   fps : 9.35
С++ (алгоритм Сергея):
   time: 96 seconds
   fps : 10.42
C++ (наш с Надей алгоритм):
   time: 22 seconds
   fps : 45.45 fps

Тестировалось всё ровно на том же ультрабуке, что и демонстрировалось на хакатоне.

Далее исходники:

С#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication5
{
    class Program
    {
        static unsafe void Main(string[] args)
        {
            const int H = 480;
            const int W = 640;
            byte[] a = new byte[H * W * 3];
            byte[] b = new byte[H * W * 3];

            System.Diagnostics.Stopwatch timer = new System.Diagnostics.Stopwatch();
            const int N = 13;
            timer.Reset();
            timer.Start();
            const int frames = 1000;
            for (int nn = 0; nn<frames; nn++)
            {
                fixed (byte* pa = &a[0])
                {
                    fixed (byte* pb = &b[0])
                    {
                        for (int n = 0; n < N; n++)
                        {
                            for (int y = 1; y < H - 1; y++)
                            {
                                for (int x = 1; x < W - 1; x++)
                                {
                                    for (int color_shift = 0; color_shift < 3; color_shift++)
                                    {
                                        *(pb + (H * y + x) * 3 + color_shift) = (byte)(0.25 * (*(pa + (H * (y - 1) + x) * 3 + color_shift)
                                        + *(pa + (H * (y + 1) + x) * 3 + color_shift)
                                        + *(pa + (H * y + x - 1) * 3 + color_shift)
                                        + *(pa + (H * y + x + 1) * 3 + color_shift)));
                                    }
                                }
                            }
                            for (int y = 1; y < H - 1; y++)
                            {
                                for (int x = 1; x < W - 1; x++)
                                {
                                    for (int color_shift = 0; color_shift < 3; color_shift++)
                                    {
                                        *(pa + (H * y + x) * 3 + color_shift) = (byte)(0.25 * (*(pb + (H * (y - 1) + x) * 3 + color_shift)
                                            + *(pb + (H * (y + 1) + x) * 3 + color_shift)
                                            + *(pb + (H * y + x - 1) * 3 + color_shift)
                                            + *(pb + (H * y + x + 1) * 3 + color_shift)));
                                    }
                                }
                            }
                        }
                    }
                }
            }

            timer.Stop();
            double dt = timer.Elapsed.TotalSeconds;
            System.Console.WriteLine("N = {0} (R = {1}), dt={2} seconds, FPS = {3}",
                N, 2 * N, dt, (frames / dt));

            System.Console.ReadLine();
        }
    }
}

С++ (алгоритм Сергея):
#include <iostream>
#include <ctime>

const int width = 640;
const int height = 480;
const size_t blurRange = 13;

enum Color {
    RED = 0,
    GREEN,
    BLUE
};

int index(int x, int y, Color color) {
    return width*y*3+x*3+color;
}

int main()
{
    volatile unsigned char* volatile in  = new unsigned char[width*height*3];
    volatile unsigned char* volatile out = new unsigned char[width*height*3];

    time_t begin;
    time(&begin);

    const int frames = 1000;

    for (int nn=0; nn<frames; nn++) {
        for (int i=0; i<blurRange; i++) {

            for (int y=1; y<height-1; y++)
                for (int x=1; x<width-1; x++) {
                    out[index(x,y,RED)]= 0.25*(
                        (float)in[index(x,y-1,RED)]+
                               in[index(x,y+1,RED)]+
                               in[index(x-1,y,RED)]+
                               in[index(x+1,y,RED)]);
                    out[index(x,y,GREEN)]= 0.25*(
                        (float)in[index(x,y-1,GREEN)]+
                               in[index(x,y+1,GREEN)]+
                               in[index(x-1,y,GREEN)]+
                               in[index(x+1,y,GREEN)]);
                    out[index(x,y,BLUE)]= 0.25*(
                        (float)in[index(x,y-1,BLUE)]+
                               in[index(x,y+1,BLUE)]+
                               in[index(x-1,y,BLUE)]+
                               in[index(x+1,y,BLUE)]);
                }

            for (int y=1; y<height-1; y++)
                for (int x=1; x<width-1; x++) {
                    in[index(x,y,RED)]=0.25*(
                        (float)out[index(x,y-1,RED)]+
                               out[index(x,y+1,RED)]+
                               out[index(x-1,y,RED)]+
                               out[index(x+1,y,RED)]);
                    in[index(x,y,GREEN)]=0.25*(
                        (float)out[index(x,y-1,GREEN)]+
                               out[index(x,y+1,GREEN)]+
                               out[index(x-1,y,GREEN)]+
                               out[index(x+1,y,GREEN)]);
                    in[index(x,y,BLUE)]=0.25*(
                        (float)out[index(x,y-1,BLUE)]+
                               out[index(x,y+1,BLUE)]+
                               out[index(x-1,y,BLUE)]+
                               out[index(x+1,y,BLUE)]);
                }
        }
    }

    time_t end;
    time(&end);
    auto seconds = difftime(end, begin);
    std::cout << float(frames)/seconds << " " << seconds << std::endl;
}

С++ (наш алгоритм):
#include <iostream>
#include <ctime>

const int width = 640;
const int height = 480;
const size_t blurRange = 13;

enum Color {
    RED = 0,
    GREEN,
    BLUE
};

int index(int x, int y, Color color) {
    return width*y*3+x*3+color;
}

template <size_t N>
struct ring_buffer {
    float buf[N];
    size_t head;
    size_t size;
    ring_buffer():head(0), size(0) {memset(buf, 0, sizeof(buf));}
    void push_back(float v) {
        if (++head >= N) {head=0;}
        if (size<N) size++;
        buf[head]=v;
    }

    float back()   {return buf[head];}
    float front()  {return buf[head!=N-1?head+1:0];}
};

int main()
{
    volatile unsigned char* volatile in  = new unsigned char[width*height*3];
    volatile unsigned char* volatile out = new unsigned char[width*height*3];

    time_t begin;
    time(&begin);

    const int frames = 1000;

    for (int nn=0; nn<frames; nn++) {
        for (int y=blurRange; y<height-blurRange; y++) {
            float red = 0;
            float green = 0;
            float blue = 0;

            ring_buffer<blurRange*2> redRows ;
            ring_buffer<blurRange*2> blueRows;
            ring_buffer<blurRange*2> greenRows;                       

            for (int x=blurRange; x<width-blurRange; x++) {
                float vr = 0;
                float vg = 0;
                float vb = 0;
                for (int y1 = y-blurRange; y1<y+blurRange; y1++) {
                    vr += in[index(x,y1,RED)  ];
                    vg += in[index(x,y1,GREEN)];
                    vb += in[index(x,y1,BLUE) ];
                }
                vr = vr/(blurRange*blurRange*4.0);
                vg = vg/(blurRange*blurRange*4.0);
                vb = vb/(blurRange*blurRange*4.0);

                auto front_r = redRows.front();
                red   += vr - redRows.front();
                green += vg - greenRows.front();
                blue  += vb - blueRows.front();
                               
                redRows.push_back(vr);
                blueRows.push_back(vb);
                greenRows.push_back(vg);

                out[index(x,y,RED)  ] = red*(blurRange*2.0/redRows.size);
                out[index(x,y,GREEN)] = green*(blurRange*2.0/greenRows.size);
                out[index(x,y,BLUE) ] = blue*(blurRange*2.0/blueRows.size);
            }
        }
    }
    time_t end;
    time(&end);
    auto seconds = difftime(end, begin);
    std::cout << float(frames)/seconds << " " << seconds << std::endl;
    return 0;
}
Y = λf.(λx.f (x x)) (λx.f (x x))

Valery Solovey

  • Hero Member
  • *****
  • Сообщений: 509
    • Просмотр профиля
Re: Мы победили :-)
« Ответ #74 : Апрель 24, 2013, 01:11:38 pm »
В OpenBSD есть утилита APM. В линуксе подобного нет? Можно жёстко выставить минимальные частоты проца. Это должно повысить качество результата тестов.