OpenCV: цикл по всем пик­се­лям изоб­ра­же­ния и сов­ме­ще­ние ука­за­те­лей

За­ча­стую мы про­грам­ми­ру­ем «как удоб­но», и счи­та­ем, что это за­да­ча ком­пи­ля­то­ра — ге­не­ри­ро­вать эф­фек­тив­ный код. При этом мы за­бы­ва­ем, на­сколь­ко тя­жёл труд ком­пи­ля­то­ра. Ведь он дол­жен ге­не­ри­ро­вать в первую оче­редь кор­рект­ный код, и уже во вто­рую оче­редь — быст­рый. По­это­му мно­гие оп­ти­ми­за­ции ком­пи­ля­тор при­ме­ня­ет очень осто­рож­но, и от­клю­ча­ет их при ма­лей­шем по­до­зре­нии на не­при­ме­ни­мость. В свя­зи с этим ком­пи­ля­то­ру нуж­но по­мо­гать, тем бо­лее, что ино­гда это сде­лать со­всем про­сто.

Рас­смот­рим за­да­чу об­хо­да всех пик­се­лей изоб­ра­же­ния cv::Mat ти­па CV_8UC1 (один unsigned char на пик­сель) на при­ме­ре ин­вер­ти­ро­ва­ния цве­тов. Ком­пи­ли­ро­вать бу­дем в Visual Studio 2010 с оп­ци­ей оп­ти­ми­за­ции /O2.

Пер­вая по­пыт­ка: Mat::at

Ти­пич­ная реа­ли­за­ция вы­гля­дит сле­дую­щим об­ра­зом:

void invert(cv::Mat &image) //image.type() == CV_8UC1
{
    for(int y(0); y < image.rows; ++y)
    {
        for(int x(0); x < image.cols; ++x)
            image.at<unsigned char>(y, x) = 255 - image.at<unsigned char>(y, x);
    }
}

Ли­стинг 1. Про­стая реа­ли­за­ция ин­вер­ти­ро­ва­ния од­но­ка­наль­но­го изоб­ра­же­ния в OpenCV

Срав­не­ние вре­мён ра­бо­ты раз­лич­ных вер­сий ко­да при­ве­де­но в кон­це ста­тьи.

К че­му здесь мож­но при­драть­ся? Кто-то мо­жет ска­зать, что на каж­дой ите­ра­ции цик­ла про­ис­хо­дит дву­крат­ный вы­зов функ­ции cv::Mat::at<>(), и же­ла­тель­но за­пом­нить ссыл­ку, воз­вра­ща­е­мую этой функ­ци­ей, во вре­мен­ную пе­ре­мен­ную, что­бы обой­тись без дву­крат­но­го вы­зо­ва. На са­мом де­ле вы­зо­вов функ­ции at по­сле ком­пи­ля­ции не оста­нет­ся. Эти функ­ции встраи­ва­ют­ся в вы­зы­ваю­щий код (inline expansion), а дву­крат­ное вы­чис­ле­ние од­но­го и то­го же ад­ре­са ком­пи­ля­тор за­ме­ня­ет на од­но­крат­ное вы­чис­ле­ние.

Вот так вы­гля­дит ас­сем­блер­ный код внут­рен­не­го цик­ла, вы­да­вае­мый ком­пи­ля­то­ром (здесь и да­лее я опус­каю на­чаль­ную про­вер­ку воз­мож­но­сти вы­пол­нить хо­тя бы од­ну ите­ра­цию, ком­мен­та­рии к ко­ду мои):

$LL3@invert:
//Вычисление адреса пикселя unsigned char *p (функция at)
mov edx, DWORD PTR [eax+44]
mov edx, DWORD PTR [edx]
imul edx, edi
add edx, DWORD PTR [eax+16]
lea esi, DWORD PTR [edx+ecx]

or dl, 255             //dl = 255
sub dl, BYTE PTR [esi] //dl -= *p
inc ecx                //++x
mov BYTE PTR [esi], dl //*p = dl

mov edx, DWORD PTR [eax+12] //edx = image.cols
cmp ecx, edx                //x < edx ?
jl SHORT $LL3@invert        //Если да, то повторяемм цикл

Ли­стинг 2. Ас­сем­блер­ный код, сге­не­ри­ро­ван­ный ком­пи­ля­то­ром Visual Studio 2010
для внут­рен­не­го цик­ла про­грам­мы ли­стин­га 1

Для на­гляд­но­сти я раз­бил ас­сем­блер­ные ин­ст­рук­ции на 3 бло­ка:

  1. вы­чис­ле­ние ад­ре­са пик­се­ля (функ­ция at), на­зо­вём этот ад­рес unsigned char *p;
  2. мо­дифи­ка­ция пик­се­ля *p = 255 - *p;
  3. на­ра­щи­ва­ние счёт­чи­ка цик­ла и про­вер­ка усло­вия вы­хо­да из цик­ла.

Ин­те­рес­но, что ин­ст­рук­ция inc ecx (на­ра­щи­ва­ние счёт­чи­ка цик­ла) на са­мом де­ле при­над­ле­жит тре­тье­му бло­ку. Ком­пи­ля­тор по­ста­вил эту ин­ст­рук­цию в се­ре­ди­ну вы­чис­ле­ния вы­ра­же­ния *p = 255 - *p, ви­ди­мо, для то­го, что­бы чем-то за­нять про­цес­сор на слу­чай про­ма­ха кэ­ша при вы­пол­не­нии чте­ния па­мя­ти sub dl, BYTE PTR [esi].

Итак, ка­кие здесь про­бле­мы? В гла­за бро­са­ют­ся 6 об­ра­ще­ний к па­мя­ти за од­ну ите­ра­цию цик­ла, 3 из ко­то­рых при­хо­дят­ся на функ­цию at (опе­ра­ция lea esi, DWORD PTR [edx+ecx] об­ра­ще­ни­ем к па­мя­ти не яв­ля­ет­ся; это про­сто из­вра­щён­ный спо­соб за­пи­сать в ре­гистр сум­му двух дру­гих ре­ги­стров). Мы зна­ем, что об­ра­ще­ние к па­мя­ти — наи­боль­шее зло, ибо оно мо­жет при­ве­сти к про­ма­ху кэ­ша и про­стою кон­вейе­ра.

Что­бы по­нять при­чи­ну об­ра­ще­ний, посмот­рим на ис­ход­ный код функ­ции at (я убрал ужас­ный assert, ко­то­рый там был):

template<typename _Tp> inline _Tp& Mat::at(int i0, int i1)
{
    return ((_Tp*)(data + step.p[0]*i0))[i1];
}

Ли­стинг 3. Ис­ход­ный код ис­поль­зу­е­мо­го ва­ри­ан­та функ­ции Mat::at

В прин­ци­пе, всё по­нят­но: к ад­ре­су пер­во­го пик­се­ля изоб­ра­же­ния при­бав­ля­ет­ся дли­на стро­ки в бай­тах, умно­жен­ная на но­мер стро­ки, и но­мер столб­ца, умно­жен­ный на раз­мер пик­се­ля. По­след­нее умно­же­ние вы­пол­ня­ет­ся опе­ра­ци­ей ин­дек­са­ции и в на­шем слу­чае от­сут­ству­ет в ас­сем­блер­ном ко­де, так как раз­мер пик­се­ля ра­вен еди­ни­це (unsigned char).

Наш враг — сов­ме­ще­ние ука­за­те­лей

Но за­чем каж­дый раз пе­ре­чи­ты­вать все эти чис­ла из па­мя­ти? Ведь не бу­дет же, на­при­мер, ши­ри­на изоб­ра­же­ния ме­нять­ся по ме­ре его ин­вер­ти­ро­ва­ния! Или бу­дет?

На са­мом де­ле по ме­ре об­ра­бот­ки изоб­ра­же­ния его ши­ри­на (и дру­гие па­ра­мет­ры) мо­гут из­ме­нить­ся! Для это­го до­ста­точ­но пе­ред вы­зо­вом функ­ции invert рас­по­ло­жить бу­фер па­мя­ти изоб­ра­же­ния по­верх ст­рук­ту­ры cv::Mat &image (ад­рес бу­фе­ра хра­нит­ся в по­ле cv::Mat::data ти­па uchar*). То есть ши­ри­на и вы­со­та об­ра­ба­ты­ва­е­мо­го изоб­ра­же­ния, ад­рес его пер­во­го пик­се­ля, дли­на стро­ки (не все­гда рав­на ши­ри­не), и дру­гие па­ра­мет­ры мо­гут яв­лять­ся пик­се­ля­ми это­го са­мо­го изоб­ра­же­ния и, зна­чит, из­ме­нить­ся при его ин­вер­ти­ро­ва­нии. О та­ком не­ве­ро­ят­ном сце­на­рии мы да­же по­ду­мать не мог­ли, а за­бот­ли­вый ком­пи­ля­тор всё преду­смот­рел и сге­не­ри­ро­вал ужас­но не­эф­фек­тив­ный, но кор­рект­ный код.

По по­во­ду сов­ме­ще­ния ука­за­те­лей смот­ри­те так­же эту ста­тью на рус­ском язы­ке.

Яв­ле­ние, ко­то­рое я опи­сал, на­зы­ва­ет­ся сов­ме­ще­ни­ем ука­за­те­лей (pointer aliasing). Воз­мож­ность та­ко­го сов­ме­ще­ния — од­на из ос­нов­ных про­блем, ме­шаю­щих ком­пи­ля­то­ру про­из­во­дить оп­ти­ми­за­ции. Что­бы убе­дить­ся, что имен­но сов­ме­ще­ние ука­за­те­лей яв­ля­ет­ся при­чи­ной пло­хо­го ко­да, рас­смот­рим функ­цию, не про­из­во­дя­щую мо­дифи­ка­цию изоб­ра­же­ния:

int sum(cv::Mat image) //image.type() == CV_8UC1
{
    int sum(0);
    for(int y(0); y < image.rows; ++y)
    {
        for(int x(0); x < image.cols; ++x)
            sum += image.at<unsigned char>(y, x);
    }
    return sum;
}

Ли­стинг 4. Мо­дифи­ка­ция изоб­ра­же­ния убра­на.
Об­ра­ти­те вни­ма­ние на то, что изоб­ра­же­ние пе­ре­да­ёт­ся не по ссыл­ке

$LL3@invert:
movzx ebx, BYTE PTR [ecx+eax]
inc eax
add esi, ebx
cmp eax, edx
jl SHORT $LL3@invert

Ли­стинг 5. Ас­сем­блер­ный код, сге­не­ри­ро­ван­ный ком­пи­ля­то­ром
для внут­рен­не­го цик­ла ли­стин­га 4. Срав­ни­те с ли­стин­гом 2

Кру­то, не прав­да ли? От цик­ла остал­ся лишь не­об­хо­ди­мый ми­ни­мум ин­ст­рук­ций: един­ствен­ное об­ра­ще­ние к па­мя­ти, сум­ми­ро­ва­ние, на­ра­щи­ва­ние счёт­чи­ка цик­ла, и про­вер­ка за­вер­ше­ния цик­ла.

От­ве­чаю на на­зрев­ший у вас во­прос: пе­ре­да­ча изоб­ра­же­ния не по ссыл­ке в ко­де из ли­стин­га 1 по­чти не ме­ня­ет ас­сем­блер­ный код внут­рен­не­го цик­ла: там про­сто не­мно­го из­ме­нит­ся ад­ре­са­ция.

Но что­бы по­лу­чить от ком­пи­ля­то­ра столь эф­фек­тив­ный код, при­шлось по­жерт­во­вать пе­ре­да­чей cv::Mat по ссыл­ке. Не­смот­ря на то, что cv::Mat осна­щён счёт­чи­ком ссылок, и ко­пи­ро­ва­ние объ­ек­та это­го клас­са не озна­ча­ет ко­пи­ро­ва­ние его дан­ных, на­клад­ные рас­хо­ды всё ещё су­ще­ствен­ны, и при­мер­но рав­ны вре­ме­ни об­ра­бот­ки (сум­ми­ро­ва­ния) мат­ри­цы 100×100 пик­се­лей. По­пыт­ка пе­ре­дать объ­ект по ссыл­ке (пусть да­же кон­стант­ной) при­ве­дёт к ге­не­ра­ции ко­да, ана­ло­гич­но­го ли­стин­гу 2. Ви­ди­мо, ком­пи­ля­тор опа­са­ет­ся, что па­ра­мет­ры объ­ек­та бу­дут из­ме­не­ны извне во вре­мя его об­ра­бот­ки.

Стро­гое сов­ме­ще­ние ука­за­те­лей

Мож­но по­ду­мать, что про­бле­мы оп­ти­ми­за­ции, свя­зан­ные с сов­ме­ще­ни­ем ука­за­те­лей, ушли с вве­де­ни­ем стро­го­го сов­ме­ще­ния ука­за­те­лей (strict pointer aliasing) в но­вых стан­дар­тах Си (C99) и Си++ (C++03). Вкрат­це, стро­гое сов­ме­ще­ние ука­за­те­лей — это ко­гда толь­ко ука­за­те­ли од­но­го ти­па ком­пи­ля­тор счи­та­ет по­до­зри­тель­ны­ми на сов­ме­ще­ние. Ис­клю­че­ние — ука­затель на char, ко­то­ро­му раз­ре­ше­но на­кла­ды­вать­ся на дру­гие ука­за­те­ли.

Си­ту­а­ция на­по­ми­на­ет си­ту­а­цию с ку­чей кри­вых сай­тов, сво­им су­ще­ство­ва­ни­ем сдер­жи­ваю­щих раз­ви­тие бра­у­зе­ров.

Од­на­ко боль­шое ко­ли­че­ство ко­да (осо­бен­но низ­ко­уров­не­во­го) за­ви­сит от воз­мож­но­сти не­стро­го­го сов­ме­ще­ния. Вся биб­лио­те­ка OpenCV про­сто рас­сы­пет­ся при ком­пи­ля­ции с вклю­чён­ным стро­гим сов­ме­ще­ни­ем, имен­но по­это­му её нуж­но ком­пи­ли­ро­вать с клю­чём -fno-strict-aliasing (при ис­поль­зо­ва­нии GCC). К сча­стью для поль­зо­ва­те­лей Windows, ком­пи­ля­тор Visual Studio не под­дер­жи­ва­ет strict aliasing, по­это­му от­клю­чать его не при­хо­дит­ся.

По­это­му бу­дем ис­кать дру­гие пу­ти по­лу­че­ния оп­ти­маль­но­го ко­да, от­лич­ные от вклю­че­ния strict aliasing в ком­пи­ля­то­ре.

Ис­поль­зу­ем Mat::ptr

Ещё раз озву­чу вы­яс­нен­ную на­ми при­чи­ну ге­не­ра­ции не­опти­маль­но­го ко­да (ли­стинг 2): ком­пи­ля­тор опа­са­ет­ся, что не­ко­то­рые па­ра­мет­ры изоб­ра­же­ния из­ме­нят­ся во вре­мя ра­бо­ты внут­рен­не­го цик­ла, из-за че­го по­сто­ян­но пе­ре­чи­ты­ва­ет их из па­мя­ти, что, в свою оче­редь, ве­дёт к не­воз­мож­но­сти вы­но­са по­вто­ряю­щих­ся вы­чис­ле­ний (на­при­мер, умно­же­ния но­ме­ра те­ку­щей стро­ки на её раз­мер) за пре­де­лы внут­рен­не­го цик­ла, так как ре­зуль­тат этих вы­чис­ле­ний мо­жет (по мне­нию ком­пи­ля­то­ра) в лю­бой мо­мент из­ме­нить­ся.

Те­перь, ко­гда из­ве­ст­на при­чи­на, с ней мож­но бо­роть­ся. Для это­го нуж­но ско­пи­ро­вать ча­сто ис­поль­зуе­мые во внут­рен­нем цик­ле дан­ные в ло­каль­ные пе­ре­мен­ные. Эти пе­ре­мен­ные, бу­дучи со­зда­ны по­сле ис­поль­зу­е­мо­го ука­за­те­ля (ука­за­те­ля на дан­ные изоб­ра­же­ния cv::Mat::data), оче­вид­но яв­ля­ют­ся от ука­за­те­ля не­за­ви­си­мы­ми (с точ­ки зре­ния ком­пи­ля­то­ра), и сов­ме­ще­ние не­воз­мож­но.

Ес­ли посмот­реть ис­ход­ный код функ­ции Mat::at (ли­стинг 3), то по­лу­ча­ет­ся, что нам на­до со­хра­нить в ло­каль­ные пе­ре­мен­ные зна­че­ния image.data и image.step.p[0], а сам ис­ход­ный код вста­вить в те­ло цик­ла. В об­щем, это пло­хое ре­ше­ние.

К сча­стью, есть го­раз­до бо­лее под­хо­дя­щая функ­ция Mat::ptr, ко­то­рую мож­но ис­поль­зо­вать за пре­де­ла­ми внут­рен­не­го цик­ла (и, зна­чит, мож­но не вол­но­вать­ся об эф­фек­тив­но­сти ге­не­ри­ру­е­мо­го для неё ко­да). Эта функ­ция воз­вра­ща­ет ука­затель на пер­вый пик­сель нуж­ной нам стро­ки:

void invert(cv::Mat image) //image.type() == CV_8UC1
{
    for(int y(0); y < image.rows; ++y)
    {
        unsigned char *const scanLine( image.ptr<unsigned char>(y) );

        for(int x(0); x < image.cols; ++x)
            scanLine[x] = 255 - scanLine[x];
    }
}

Ли­стинг 6. Ис­поль­зу­ем функ­цию ptr

$LL3@invert:
or  dl, 255
sub dl, BYTE PTR [eax+ecx]
inc eax
mov BYTE PTR [eax+ecx-1], dl
mov edx, DWORD PTR [esi+12]
cmp eax, edx
jl  SHORT $LL3@invert

Ли­стинг 7. Ас­сем­блер­ный код внут­рен­не­го цик­ла из ли­стин­га 6

Об­ра­ти­те вни­ма­ние на то, как на­стой­чи­во ком­пи­ля­тор пы­та­ет­ся вста­вить на­ра­щи­ва­ние счёт­чи­ка цик­ла до за­пи­си ре­зуль­ти­рую­ще­го зна­че­ния. Это да­же при­во­дит к то­му, что ком­пи­ля­тор вы­нуж­ден об­рат­но от­нять при­бав­лен­ную еди­ни­цу при за­пи­си в па­мять: mov BYTE PTR [eax+ecx-1], dl. Тем не ме­нее, этот код бо­лее эф­фек­ти­вен, чем ес­ли бы на­ра­щи­ва­ние счёт­чи­ка бы­ло по­сле за­пи­си в па­мять, так как эко­но­мит­ся один такт при про­ма­хе кэ­ша.

Оста­лось од­но лиш­нее чте­ние па­мя­ти для ши­ри­ны изоб­ра­же­ния. Из­ба­вим­ся от не­го, со­хра­няя раз­ме­ры в ло­каль­ных пе­ре­мен­ных:

void invert(cv::Mat &image) //image.type() == CV_8UC1
{
    int const imageWidth(image.cols), imageHeight(image.rows);
   
    for(int y(0); y < imageHeight; ++y)
    {
        unsigned char *const scanLine( image.ptr<unsigned char>(y) );

        for(int x(0); x < imageWidth; ++x)
            scanLine[x] = 255 - scanLine[x];
    }
}

Ли­стинг 8. Раз­ме­ры изоб­ра­же­ния со­хра­не­ны в ло­каль­ных пе­ре­мен­ных

$LL3@invert:
or  bl, 255
sub bl, BYTE PTR [ecx+eax]
inc ecx
mov BYTE PTR [ecx+eax-1], bl
cmp ecx, esi
jl  SHORT $LL3@invert

Ли­стинг 9. Ас­сем­блер­ный код внут­рен­не­го цик­ла из ли­стин­га 8.
По срав­не­нию с ли­стин­гом 7 ис­чез­ла опе­ра­ция чте­ния ши­ри­ны изоб­ра­же­ния из па­мя­ти

Мы ви­дим, что ком­пи­ля­тор со­хра­нил ши­ри­ну изоб­ра­же­ния в ре­ги­стре esi, и не чи­та­ет её каж­дый раз из па­мя­ти.

Мож­но ли вы­жать из это­го ко­да ещё что-ни­будь? Ко­неч­но! За­ме­тим, что ес­ли кру­тить цикл не по воз­рас­та­нию, а по убы­ва­нию, то цикл все­гда бу­дет ид­ти до ну­ля, и ком­пи­ля­то­ру во­об­ще не на­до бу­дет ис­поль­зо­вать cmp для про­вер­ки усло­вия оста­нов­ки, так как каж­дая ариф­ме­ти­че­ская опе­ра­ция со­хра­ня­ет во фла­го­вых ре­ги­страх про­цес­со­ра знак сво­е­го ре­зуль­та­та. Со­от­вет­ствен­но, в этом слу­чае не нуж­но со­хра­нять раз­ме­ры изоб­ра­же­ния в ло­каль­ных пе­ре­мен­ных.

Кро­ме то­го, од­на опе­ра­ция ис­поль­зу­ет­ся для за­груз­ки чис­ла 255 в ре­гистр bl. Ес­ли вме­сто вы­чи­та­ния ис­поль­зо­вать би­то­вое от­ри­ца­ние (стран­но, что ком­пи­ля­тор сам не до­га­дал­ся об этом), то мож­но сэко­но­мить ещё од­ну опе­ра­цию. В ито­ге по­лу­ча­ем:

void invert(cv::Mat &image) //image.type() == CV_8UC1
{
    for(int y(image.rows - 1); y >= 0; --y)
    {
        unsigned char *const scanLine( image.ptr<unsigned char>(y) );

        for(int x(image.cols - 1); x >= 0 ; --x)
            scanLine[x] = ~scanLine[x];
    }
}

Ли­стинг 10. На­прав­ле­ния хо­да цик­лов из­ме­не­ны.
Вме­сто вы­чи­та­ния при­ме­не­но би­то­вое от­ри­ца­ние

$LL3@invert:
dec ecx
mov dl, BYTE PTR [ecx+eax+1]
not dl
mov BYTE PTR [ecx+eax+1], dl
jns SHORT $LL3@invert

Ли­стинг 11. Ас­сем­блер­ный код внут­рен­не­го цик­ла из ли­стин­га 10

Об­ра­ти­те вни­ма­ние, что умень­ше­ние счёт­чи­ка цик­ла ком­пи­ля­тор по­ста­вил ещё рань­ше, и те­перь обе опе­ра­ции об­ра­ще­ния к па­мя­ти име­ют +1 для ком­пен­са­ции это­го преж­де­вре­мен­но­го вы­чи­та­ния.

Под­ве­дём ито­ги. Код из ли­стин­га 1 мы мо­дифи­ци­ро­ва­ли, по­лу­чив код из ли­стин­га 11. При этом в но­вом ко­де все­го на од­ну строч­ку боль­ше, и од­на из стро­чек су­ще­ствен­но ко­ро­че, так что нель­зя од­но­знач­но ска­зать, ка­кой из ва­ри­ан­тов бо­лее сло­жен. В ре­зуль­та­те вме­сто 12-ти ас­сем­блер­ных ин­ст­рук­ций, со­дер­жа­щих 6 об­ра­ще­ний к па­мя­ти, мы по­лу­чи­ли 5 ин­ст­рук­ций и 2 об­ра­ще­ния к па­мя­ти.

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

И, на­по­сле­док, не удер­жусь, при­ве­ду ва­ри­ант с ите­ра­то­ром:

void invert(cv::Mat &image) //image.type() == CV_8UC1
{
    for(cv::MatIterator_<unsigned char> i( image.begin<unsigned char>() );
    i != image.end<unsigned char>(); ++i)
        *i = ~*i;
}

Ли­стинг 12. Об­ход мат­ри­цы при по­мо­щи ите­ра­то­ра

Это­му изящ­но­му ко­ду со­от­вет­ству­ет бо­лее сот­ни ас­сем­блер­ных ин­ст­рук­ций, по­это­му не при­во­жу их здесь.

Срав­не­ние вре­ме­ни ра­бо­ты раз­лич­ных вер­сий ко­да

Мой про­цес­сор: Intel Core i5 M 460 2.53GHz, 2 яд­ра + Hyper-threading. Код за­пус­кал­ся на од­ном яд­ре для изоб­ра­же­ний 1024×1024 пик­се­ля (1 ме­га­байт) и 8192×8192 пик­се­ля (64 ме­га­бай­та).

Ва­ри­ант ко­даВре­мя ра­бо­ты (сек)
1024×1024 пик­се­ля
Вре­мя ра­бо­ты (сек)
8192×8192 пик­се­ля
1Mat::at (ли­стинг 1)0.002150.146
2Mat::ptr (ли­стинг 6)0.001310.089
3Раз­ме­ры в пе­ре­мен­ных (ли­стинг 8)0.001300.088
4Цик­лы по убы­ва­нию (ли­стинг 10)0.001300.087
5Ите­ра­тор (ли­стинг 12)0.02111.36

Таб­ли­ца 1. Вре­ме­на ра­бо­ты раз­лич­ных вер­сий ко­да. Мень­ше — луч­ше

При­ят­но осо­зна­вать, что тот ва­ри­ант (но­мер 3), ко­то­рый я ин­ту­и­тив­но вы­брал пол­то­ра го­да на­зад, ко­гда на­чал ис­поль­зо­вать OpenCV в сво­ей де­я­тель­но­сти, те­перь по­лу­чил обос­но­ва­ние. Я люб­лю скан­лай­ны со вре­мён Delphi. Там был ме­тод ScanLine у TBitmap.

Мы ви­дим, что об­ход мат­ри­цы при по­мо­щи Mat::ptr при­мер­но в 1.6 раз быст­рее, чем при по­мо­щи Mat::at. Даль­ней­шие оп­ти­ми­за­ции, не­смот­ря на оче­вид­ное со­кра­ще­ние объ­ё­ма ис­пол­ня­е­мо­го ко­да, к ро­сту про­из­во­ди­тель­но­сти не при­ве­ли. Ви­ди­мо, су­пер­ска­ляр­ность про­цес­со­ра по­ела всю не­эф­фек­тив­ность ко­да. Ва­ри­ант с ите­ра­то­ром ока­зал­ся в 16 раз мед­лен­нее са­мо­го быст­ро­го ва­ри­ан­та, по­это­му его ис­поль­зо­вать не сле­ду­ет.

За­клю­чи­тель­ные со­ве­ты

  • Посмот­ри­те, ка­кие внеш­ние дан­ные (дан­ные, на ко­то­рые ва­шей функ­ции да­ны ука­за­те­ли или ссыл­ки) вы ак­тив­но ис­поль­зу­е­те внут­ри функ­ции. Сде­лай­те ко­пии этих дан­ных в ло­каль­ных пе­ре­мен­ных, ес­ли вы уве­ре­ны, что эти дан­ные не долж­ны ме­нять­ся по хо­ду ра­бо­ты функ­ции.

  • Ес­ли у вас есть ука­за­те­ли, ко­то­рые ука­зы­ва­ют на дан­ные, не пе­ре­се­каю­щие­ся ни с чем дру­гим в ва­шей функ­ции, то по­мо­ги­те ком­пи­ля­то­ру — ис­поль­зуй­те клю­че­вое сло­во __restrict (не осве­ще­но в дан­ной ста­тье). Осо­бен­но это по­лез­но для ар­гу­мен­тов функ­ций. К со­жа­ле­нию, __restrict не ра­бо­та­ет для ссылок.

  • В ка­че­стве счёт­чи­ка и в усло­вии оста­нов­ки цик­ла ис­поль­зуй­те толь­ко ло­каль­ные пе­ре­мен­ные. Осо­бен­но хо­ро­шо, ко­гда в усло­вии оста­нов­ки цик­ла ис­поль­зу­ет­ся срав­не­ние счёт­чи­ка с ну­лём.

  • В прин­ци­пе, ком­пи­ля­тор мо­жет оп­ти­ми­зи­ро­вать Mat::at до пре­дель­но оп­ти­маль­но­го со­стоя­ния (смот­ри­те ли­стин­ги 4 и 5), но для это­го долж­ны вы­пол­нить­ся не­сколь­ко усло­вий: объ­ект cv::Mat (и, зна­чит, па­ра­мет­ры, вхо­дя­щие в функ­цию at) долж­ны быть ло­каль­ны от­но­си­тель­но функ­ции, и изоб­ра­же­ние не долж­но мо­дифи­ци­ро­вать­ся. Но луч­ше, всё же, ис­поль­зо­вать функ­цию Mat::ptr, так как она ра­бо­та­ет за пре­де­ла­ми внут­рен­не­го цик­ла и, зна­чит, не яв­ля­ет­ся ис­точ­ни­ком не­эф­фек­тив­но­сти.

  • Не ис­поль­зуй­те ите­ра­то­ры для об­хо­да cv::Mat.

220 отзывов на запись «OpenCV: цикл по всем пик­се­лям изоб­ра­же­ния и сов­ме­ще­ние ука­за­те­лей»

It is also possible that Zynga’s chosen advertising network is to blame if we consider the case of the New York Times’ website
generic lisinopril
Cafergot Online
BUY VPXL
Buspar Without A Prescription
Retin-A
antabuse
propranolol online
motilium otc
buy propranolol
cheap anafranil
whoah this blog is fantastic i really like studying your articles. Keep up the good paintings! You understand, many individuals are looking around for this info, you could aid them greatly.
Fluticasone Propionate
sildalis visa
cialis medicine
wellbutrin without prescription
buy nexium
buy fluoxetine
wh0cd856566
wh0cd236726
wh0cd9446
reverse phone number free lookup how to do reverse phone lookup for free phone lookup free results free phone reverse number lookup
best free reverse cell phone lookup with name reverse cell phone lookup
for free real free reverse phone lookup with name for free phone number lookup
reverse phone number lookup usa free reverse phone number lookup cell phone lookup free reverse free reverse phone lookup for free really
is there a reverse phone lookup that is really free cell phone usa reverse phone lookup free lookup free reverse cell phone lookup free
really free reverse phone lookup with name reverse phone lookup for free reverse cell phone number lookup with name reverse lookup cell phone
free
best free reverse phone lookup phone reverse lookup free results
reverse phone lookup by address free complete reverse cell phone lookup
phone reverse lookup free reverse directory lookup phone number name reverse lookup cell phone
numbers for free reverse phone lookup free account
best free cell phone number reverse lookup reverse phone
lookup reverse phone lookup with name for free free phone
reverse lookup cell
free cell phone number reverse lookup reverse number lookup free phone reverse lookup cell phone cell phone
reverse number lookup free
reverse phone lookup cell phone free online free phone reverse lookup cell completely free reverse phone number lookup
reverse lookup phone number
free phone reverse lookup with name reverse lookup phone number free phone lookup free reverse phone lookup for cell phones reverse
cell phone number reverse phone number lookup name free lookup free
free reverse phone number lookup free reverse lookup of phone numbers
Thanks for any other informative website.
Where else may just I am getting that type of info written in such a perfect manner?
I have a project that I’m simply now running on, and I have been on the look out for such info.
Every weekend i used to pay a visit this site, as i wish for enjoyment, as this this website conations really pleasant funny material too.
First off I want to say terrific blog! I had a quick question in which I’d like
to ask if you don’t mind. I was curious to
find out how you center yourself and clear your mind prior to writing. I have had a difficult time clearing my thoughts in getting my ideas out there. I truly do take pleasure in writing however it just seems like the first 10 to 15 minutes are wasted simply
just trying to figure out how to begin. Any ideas or
hints? Appreciate it!
Hi there! I just would like to give you a big thumbs up for the great info you’ve got here on this post. I’ll be returning to your web site for more soon.
I always emailed this web site post page to all my associates, as
if like to read it after that my contacts will too.
May I simply say what a comfort to uncover an individual
who really knows what they’re talking about on the internet.
You certainly realize how to bring an issue to light and make it important. A lot more people ought to look at this and understand this
side of the story. It’s surprising you aren’t more popular since you certainly have the
gift.
I have been exploring for a little for any high quality articles or weblog posts on this
kind of area . Exploring in Yahoo I eventually stumbled upon this
site. Reading this info So i am happy to express that I’ve an incredibly
good uncanny feeling I found out just what I needed.
I most definitely will make certain to do not overlook this site and give it
a look regularly.
Does your blog have a contact page? I’m having problems locating it but, I’d like to shoot you an email.
I’ve got some recommendations for your blog you might be interested in hearing.
Either way, great website and I look forward to seeing it develop over time.
The other day, while I was at work, my sister stole my apple ipad and tested to see if it can survive a 25 foot
drop, just so she can be a youtube sensation. My iPad is now broken and she has 83 views.
I know this is completely off topic but I had to share it with someone!
Hello there! This post could not be written any better!
Reading this post reminds me of my previous room mate!
He always kept talking about this. I will forward this
page to him. Pretty sure he will have a good read. Thanks for sharing!
Hey I know this is off topic but I was wondering if you knew of any widgets I could add
to my blog that automatically tweet my newest twitter updates.
I’ve been looking for a plug-in like this for quite some
time and was hoping maybe you would have some experience with something
like this. Please let me know if you run into anything. I truly enjoy reading
your blog and I look forward to your new updates.
Thanks on your marvelous posting! I truly enjoyed reading
it, you’re a great author. I will be sure to bookmark your blog
and will eventually come back from now on. I want to encourage continue
your great posts, have a nice weekend!
Its like you read my mind! You appear to know a lot
about this, like you wrote the book in it or something.
I think that you could do with a few pics to drive the message
home a bit, but instead of that, this is great blog.
An excellent read. I’ll certainly be back.
Hi my friend! I wish to say that this post is amazing, nice written and
come with approximately all important infos. I would
like to look extra posts like this .
I know this web page presents quality dependent
articles and other data, is there any other web site which gives these stuff in quality?
Hello! This is kind of off topic but I need some advice from an established blog.
Is it tough to set up your own blog? I’m not very techincal but I can figure things
out pretty quick. I’m thinking about making my own but I’m not sure where
to begin. Do you have any ideas or suggestions?
Cheers
It’s perfect time to make some plans for the future
and it is time to be happy. I have read this post and if
I could I want to suggest you some interesting
things or advice. Maybe you could write next articles referring to this article.
I want to read even more things about it!
It’s impressive that you are getting thoughts from this article
as well as from our argument made at this place.
I am now not certain the place you are getting your info, but great topic.
I needs to spend a while finding out more or understanding more.
Thank you for excellent information I used
to be looking for this information for my mission.
If some one needs to be updated with hottest technologies then he must be visit this website and be up to date every day.
It’s going to be finish of mine day, however before finish
I am reading this wonderful paragraph to improve my know-how.
Attractive part of content. I just stumbled upon your site and in accession capital
to assert that I acquire actually enjoyed account your blog posts.
Any way I will be subscribing for your augment or even I
fulfillment you access constantly quickly.
Your style is very unique in comparison to other people I’ve
read stuff from. Thank you for posting when you have the opportunity, Guess I’ll just bookmark this blog.
I am actually happy to glance at this webpage posts which carries lots of helpful information, thanks
for providing such data.
Sweet blog! I found it while searching on Yahoo News.
Do you have any suggestions on how to get listed in Yahoo News? I’ve been trying for a while but I never seem to get there!
Thanks Here is my page — silk lash extensions london
You actually make it seem so easy with your presentation however I find this topic to be really something which I
believe I’d never understand. It sort of feels too complex and very wide for me.
I am having a look forward on your subsequent put
up, I will try to get the grasp of it!
Thanks for the auspicious writeup. It actually
used to be a enjoyment account it. Look advanced to far added agreeable from you!
By the way, how could we be in contact? my blog post: hair treatment; echelon.perxadvantage.com,
Wow, awesome blog layout! How long have you been blogging for?
you make blogging look easy. The overall look of
your site is excellent, let alone the content! My web blog; mink lashes cruel
What’s Happening i am new to this, I stumbled upon this I have discovered
It positively useful and it has helped me out loads.
I am hoping to give a contribution & aid other customers like its helped me. Great job. Also visit my site madden nfl mobile free coins no survey
Hello there! This post couldn’t be written any better! Going
through this article reminds me of my previous roommate! He constantly kept preaching about this. I will send this information to him.
Fairly certain he’ll have a very good read. Thank you for sharing! Also visit my web site; csgo skins price, https://www.smiletug.com/people/stacey01w74,
If you wish for to take much from this piece of writing then you have to apply these techniques to your won webpage. Review my web page; mink individual lashes kit
WOW just what I was searching for. Came here by searching for fifa 17 coins generator Feel free to surf to my web site — fifa coins free ps3 (http://www.hildebrandt.de/)
My partner and I stumbled over here coming from a different web page and thought I might check things out. I like what I see so now i am following you.
Look forward to looking at your web page repeatedly. Feel free to surf to my weblog: csgo skins price check
An intriguing discussion is worth comment.
I believe that you need to publish more about this issue,
it might not be a taboo subject but usually people do not discuss these subjects.
To the next! Best wishes!!
WOW just what I was searching for. Came here by
searching for cs go skins for money my website :: cs go skins price checker (http://www.gamunu.info)
Oh my goodness! Incredible article dude! Many thanks, However I am encountering troubles with your RSS.
I don’t understand the reason why I am unable to join it. Is there anyone else
having the same RSS problems? Anyone that knows the solution will you kindly respond?
Thanx!! Here is my homepage: best cs go skin betting
That is really attention-grabbing, You’re an excessively
skilled blogger. I have joined your rss feed and
stay up for in search of extra of your wonderful post.
Additionally, I’ve shared your web site in my social networks Also visit my site :: fifa 17 coins xbox one
Amazing! Its actually awesome post, I have got much clear
idea concerning from this article. my web page … professional mink lash kit
I take pleasure in, result in I discovered exactly
what I used to be looking for. You’ve ended my four day lengthy hunt! God Bless you man. Have a nice day. Bye
Excellent pieces. Keep writing such kind of info on your blog. Im really impressed by your site.
Hey there, You have performed an excellent job. I’ll certainly digg
it and individually recommend to my friends. I’m confident they’ll be benefited from this site.
Wow, this paragraph is pleasant, my sister is analyzing these things,
so I am going to inform her.
I am regular reader, how are you everybody? This paragraph posted at this website is actually nice. Here is my website — fifa coins ps4 ebay
Do you mind if I quote a couple of your posts as long as I
provide credit and sources back to your site? My blog site is in the
exact same niche as yours and my users would truly benefit from
some of the information you present here. Please let me know if this alright with you.
Cheers! My blog … cs go knife skins for sale (http://www.wikipizza.com/)
hello!,I really like your writing so so much! proportion we
keep in touch extra about your article on AOL?
I require a specialist on this house to solve my problem.
Maybe that’s you! Having a look ahead to see you. my weblog — silk lash extensions wholesale
Thanks for sharing your thoughts on free dating sites no fees.
Regards
I feel that is one of the most significant information for me.
And i am satisfied studying your article. But want to
remark on some basic things, The site taste
is great, the articles is in reality nice : D. Just right job, cheers
Very good information. Lucky me I ran across your website by accident (stumbleupon).
I have book marked it for later!
Great post. I was checking constantly this blog and I am impressed!
Very useful info specifically the last part I care for such info much.
I was looking for this particular info for a long time. Thank you and good luck.
I all the time used to read piece of writing in news papers but now as I am
a user of net therefore from now I am using net for content, thanks to web.
Hi there, this weekend is good in favor of me, as this moment i am reading this fantastic educational post here at
my home. Also visit my web-site: madden mobile online coin generator no download no survey
When I initially commented I clicked the «Notify me when new comments are added» checkbox and
now each time a comment is added I get several e-mails with the same comment. Is there any way you can remove me from that service?
Cheers! Also visit my site :: cs go skins price checker (http://www.kansasco-op.coop)
Hey there! Someone in my Myspace group shared this website with us so I came to take a look.
I’m definitely enjoying the information. I’m book-marking and will be tweeting this
to my followers! Excellent blog and fantastic design. Have a look at my blog … mink lash extensions reviews
This design is spectacular! You obviously know how
to keep a reader amused. Between your wit and your
videos, I was almost moved to start my own blog (well, almost…HaHa!) Wonderful job.
I really enjoyed what you had to say, and more than that,
how you presented it. Too cool!
Tirage divinatoire amour gratuit les signes horoscope Feel free to surf to my weblog — Get Laid free Tonight
I’m don’t certain the spot you are having your
info, although great subject matter. I need to take your time learning more or maybe figuring
out more. Thank you for superb details I found myself looking for this specific information at my own purpose. My web page :: http://Games4fun.fr
Hello it really is me, I am additionally checking out
this specific website regularly, this particular website is actually pleasurable plus the users tends to be truly revealing pleasurable head. my homepage sex facebook
Tarot tirage gratuit en ligne mon avenir dans les cartes Here is my web blog :: http://Ebooksget.us/groups/dating-assistance-for-guys-just-how-to-behave-on-first-date/
Safeguard sufficient poultry toys within the top a portion of
the bird cage to provide several experience of privateness, allowing your own puppy parrot
in order to hide around them. It is not created for safe or maybe big-scale application.
Quick whenever you understand what you’re looking for in a very product or service and difficult once you don’t
has a process for buying the greatest Clickbank goods. Feel free to visit my web blog — Facebookofsex.Com
In many cases, why not participate in the video game once you tend to be sufficient able in order to win. For instance, and commuting on a variety
of amazing apps are created for a variety of functions.
The man jumps, candy crush saga swindle surges, and many others.
0 or higher so that they can play the video game consuming labeled drinks,
creating certain brand name snacks. Here is my page … facebook en sex
we appreciate, end up inn I discovered exahtly things I used to be using a peek when it comes to. You may have finished my own four time long hunt! Jesus Bless you people. Need a good day. Bye my page :: Storedtheapp.com
sensacje xx wieku obtain… Feel free to surf to my web-site … lathie.Senerew.com
Incredible issues here. I am very happy to
check the write-up. Thanks a lot a lot and i am taking a look forward at reach your. Here is my site; free local hookup
When I initially commented I clicked the «inform me personally when brand-new reviews include included» checkbox and today each time
the opinion are added I have 3 e-mail with the exact same remark.
Can there be any way you are able to remove myself coming from which solution? Thank you so much! Also visit my webpage — personals
protection agencies newer jersey… Here is my page: a hook up
I’m not sure why but this site is loading incredibly slow for me.
Is anyone else having this issue or is it a issue on my end?
I’ll check back later on and see if the problem still exists.
WOW just what I was looking for. Came here by searching
for mink lash extensions nyc Review my website — silk lash extensions adelaide
Have you ever considered about including a little bit more than just your articles?
I mean, what you say is important and everything. But imagine if you added some great photos or videos
to give your posts more, «pop»! Your content is excellent but with pics
and videos, this website could definitely be one of the
best in its niche. Awesome blog! Check out my web blog; madden mobile coin shop
Hi! Someone in my Myspace group shared this site
with us so I came to give it a look. I’m definitely enjoying the information. I’m bookmarking and will be tweeting this to my followers!
Outstanding blog and outstanding design. Here is my weblog :: counter strike go skin trade
Thanks for every other fantastic article. The place else could anybody get that kind of information in such an ideal manner of writing?
I’ve a presentation next week, and I’m at the search for such info. My web blog :: csgo skins free spin
I will right away grasp your rss feed as I can’t to find your email subscription hyperlink or e-newsletter service.
Do you’ve any? Kindly permit me recognise in order
that I may just subscribe. Thanks. my blog post — mink lash strips wholesale
We’re a group of volunteers and opening a new scheme in our community.
Your site provided us with valuable info to work on. You’ve done an impressive job and our
whole community will be grateful to you. My blog; buy cheap nba live coins
After checking out a handful of the blog articles on your blog, I really appreciate your technique of writing a blog.
I book-marked it to my bookmark site list and will be checking back soon. Please check out my web
site as well and let me know what you think. Also visit my web-site — csgo skins free hack
I visited several sites but the audio quality for audio songs current at this web page
is truly superb. Here is my web site mink lashes for sale
For me sweet break tale task is also a process athletics since you just have a finite moves at break all
people jelly’s, there are pleasing bombs that you have to must crush before the number of moves runs
aside, candies which are supposed crazy with every solitary
move you create as there are the timed online game that you need to accomplish a particular areas
as part of sixty-seconds to complete the amount.
The essential latest problem is will the fact is Swamp, plus the software gives
you the entire traits take into account when you look at the relaxing for some good-looking rush-inducing 425.
But, as opposed to the typical sugar packed candy layered raisins this coronary center wholesome
choice is practically nothing to come quickly to feeling bad about indulging
within. my web blog — facebook of sex 2016 (sigmaclub-ui.org)
That is very attention-grabbing, You’re an overly professional blogger. I’ve joined your rss feed and look forward to looking for extra of your excellent post.
Additionally, I have shared your site in my social networks Check out my weblog: fifa 17 coins free generator
You actually make it seem really easy along with your presentation however I in finding this topic to be actually one thing that
I feel I might never understand. It sort of feels too complex and extremely broad for me. I’m taking a look ahead in your subsequent post, I will try to get the
hang of it! Also visit my web page; best cs go skin betting [z01.net]
Hello it’s me, I am also visiting this website on a regular
basis, this web site is in fact pleasant and the
viewers are in fact sharing good thoughts. my website csgo skins betting sites
I am incredibly happy to discover this great site. I would like at saying
thanks to your when it comes to people opportunity because of this fantastic browse!!
I surely adored each little bit of that and I also have you bookmarked at discover something new
within your website. my web site sex free fecbook
Hi there friends, its fantastic article on the topic of cultureand entirely defined, keep it up all
the time. Feel free to surf to my web page … nba live coins generator
Hey there just wanted to give you a quick heads up. The words in your article seem to be running off the screen in Chrome.
I’m not sure if this is a format issue or something
to do with internet browser compatibility but I figured I’d
post to let you know. The design and style look great though!
Hope you get the issue resolved soon. Cheers
Incredible story there. What occurred after?
Take care! My website; madden mobile unlimited coins no survey no download
If some one wants to be updated with most recent technologies therefore he must be go
to see this web site and be up to date all the time. My site … 1 (http://www.seoulmariacenter.net)
Generally I do not read post on blogs, but
I would like to say that this write-up very pressured
me to check out and do so! Your writing taste has been surprised me. Thank you, quite nice post. My weblog :: cs go skins steam workshop (bestsns.kr)
Hello, i believe that i saw you visited my website so i got here to
go back the prefer?.I’m attempting to in finding things to improve my web site!I guess its adequate to make use of a few of your ideas!! My web site real mink lashes for sale
I am genuinely delighted to read this webpage posts which carries plenty of
helpful information, thanks for providing these data. Feel free to visit my website — strong gaming punch (Marilou)
Hi there! Would you mind if I share your blog with my zynga group?
There’s a lot of people that I think would really enjoy your
content. Please let me know. Thanks Visit my weblog … cs go skin betting websites (hgdvl.hnue.edu.vn)
I always spent my half an hour to read this web site’s content everyday
along with a mug of coffee. Also visit my web site :: nba live coins and cash
It’s a pity you don’t have a donate button! I’d without a doubt donate to this fantastic blog!
I suppose for now i’ll settle for bookmarking and adding
your RSS feed to my Google account. I look forward to
fresh updates and will share this blog with my Facebook group.
Talk soon! Also visit my page :: silk lashes for sale (Yong)
This site was… how do you say it? Relevant!! Finally I have found
something that helped me. Thank you! Feel free to surf to my blog … top xbox games [Eli]
Wow! In the end I got a weblog from where I be able to genuinely take helpful facts concerning my
study and knowledge. Here is my website; csgo skins for cash (svetaforrr.ru)
I seriously love your site.. Pleasant colors & theme.
Did you develop this website yourself? Please reply back as I’m
planning to create my own personal website and would
like to know where you got this from or exactly what the theme is called. Cheers! Here is my homepage; csgo skins free, Tanja,
Spot on with this write-up, I truly believe that this amazing site needs
much more attention. I’ll probably be returning to read through more,
thanks for the information! Here is my website: mink lash extensions dublin
Yes! Finally something about manicure.
It’s actually a great and helpful piece of
info. I’m happy that you shared this helpful info with us. Please stay us informed like this. Thanks for sharing. Feel free to surf to my homepage … cs go skins trade up (Shani)
Great article, exactly what I was looking for. Also visit my blog post fifa 17 coins ps4 review
Hello there! This post couldn’t be written any better!
Reading through this post reminds me of my old room mate!
He always kept talking about this. I will forward this post to him.
Fairly certain he will have a good read. Many thanks for sharing! my blog post mink eyelash extensions for sale
Hi, I think your website might be having browser compatibility issues.
When I look at your website in Chrome, it looks fine but when opening in Internet Explorer,
it has some overlapping. I just wanted to give you a quick heads up!
Other then that, superb blog! my site — csgo skins free code (Claribel)
Hmm is anyone else encountering problems with the pictures on this
blog loading? I’m trying to find out if its a problem on my end or if it’s the blog.
Any suggestions would be greatly appreciated. My blog :: mink eyelash extensions for sale — Candelaria -
Hi i am kavin, its my first occasion to commenting
anyplace, when i read this piece of writing i thought i could also create comment due to this sensible article. Have a look at my web site: madden mobile coin sale
I’m not sure where you are getting your information, but great topic.
I needs to spend some time learning more or understanding
more. Thanks for wonderful info I was looking for this information for my mission. Visit my web blog csgo skins price list
Wow, incredible blog layout! How long have you been blogging for?
you made blogging look easy. The overall look of your site is excellent,
let alone the content! My site :: mink eyelashes amazon (Davis)
Hi! This is kind of off topic but I need some guidance from an established blog.
Is it very difficult to set up your own blog? I’m not very techincal but I
can figure things out pretty fast. I’m thinking about setting up my own but I’m not sure where to begin. Do you have any tips or suggestions? With thanks Here is my web site: nba live coins and cash (Ferdinand)
Its like you learn my mind! You seem to know
so much approximately this, like you wrote the guide in it or something.
I think that you could do with some % to pressure the message house a little bit, however other than that, that
is excellent blog. A great read. I will definitely be
back. my web-site: cs go skin trade reddit
I am regular visitor, how are you everybody? This post posted at this site is really fastidious.
You’ve made some good points there. I looked on the web to learn more about the issue and found most people will go along with your views on this site. Review my site … madden mobile free coins cheat (http://www.apft.edu.in)
I read this post fully about the resemblance of newest and
preceding technologies, it’s amazing article. Here is my blog … mink strip eyelashes australia (Alvin)
Appreciate it, Many discussion board content. Also visit my webpage vetepsa.com
Nice blog site right here! In addition your site loads up very
fast! Specifically web variety are you presently making use of?
May I get the affiliate marketer link to your own variety?
I wish my site filled upwards as fast as your own lol Feel free to surf to my blog 7=0:>
Hi there just desired to promote you a simple minds upwards. The particular book within your content material seem to be operating from
the monitor within Firefox. I don’t know should this be the formatting problems
or something to do with internet browser being compatible but I realized I’d publish to inform you.
The style and magnificence look wonderful however! Wish you get the difficulty dealt with before long. Many Thanks My web site facebooksex 2016
Wonderful items from you, man. I have keep in mind your stuff prior to and you
are simply extremely magnificent. I actually like what you have obtained here, certainly like what you’re saying and the way through which you
say it. You’re making it enjoyable and you still take care of to stay it sensible. I can not wait to read far more from you. That is really a terrific website. Also visit my webpage; nba mobile coins for free (Javier)
Definitely believe that that you stated. Your favourite reason appeared to be
at the web the easiest thing to be aware of. I say to you, I certainly get irked even as other folks think about worries that they plainly don’t know
about. You controlled to hit the nail upon the highest and also defined out
the entire thing without having side effect , people
could take a signal. Will probably be again to get more.
Thanks my webpage :: silk lash extensions melbourne
Hey there this is somewhat of off topic but I
was wondering if blogs use WYSIWYG editors or if you have to manually code
with HTML. I’m starting a blog soon but have no coding know-how so I wanted
to get guidance from someone with experience.
Any help would be greatly appreciated! My website … nba live coins reddit (Geri)
Keep on writing, great job!
Thanks for ones marvelous posting! I genuinely enjoyed reading it,
you could be a great author.I will ensure that I
bookmark your blog and will eventually come back someday.
I want to encourage you to ultimately continue your great job, have a nice day! Feel free to visit my website fifa 17 coins for sale ebay (Luann)
Hey I know this is off topic but I was wondering if you
knew of any widgets I could add to my blog that automatically tweet my newest
twitter updates. I’ve been looking for a plug-in like this
for quite some time and was hoping maybe you would have some
experience with something like this. Please let me know if you run into anything.
I truly enjoy reading your blog and I look forward to your new updates. My website :: cs go skins price checker (Josie)
Excellent article. I will be going through a few of these
issues as well.. Also visit my homepage — cheapest madden mobile coins (Denise)
It’s great that you are getting ideas from this post as well as from
our discussion made here. Here is my weblog :: fifa coins ps4 fifa 17 (Monserrate)
Fantastic blog! Do you have any suggestions for aspiring writers?
I’m hoping to start my own website soon but I’m a little
lost on everything. Would you advise starting with a
free platform like WordPress or go for a paid option? There are so many choices out there that I’m totally confused ..
Any ideas? Thanks a lot! my site :: silk lashes cruelty free (Dylan)
Hi there i am kavin, its my first occasion to commenting anywhere, when i read this article i thought
i could also make comment due to this sensible article. Here is my site … silk lash extensions review (Maxwell)
Ahaa, its nice conversation regarding this post here
at this web site, I have read all that, so now me also commenting at this place. Feel free to visit my page … cheap pubg skins (Malcolm)
I every time used to study paragraph in news papers
but now as I am a user of web therefore from now I am using net for articles or reviews,
thanks to web. Here is my blog post … hut coins
I think this is among the most important
info for me. And i’m glad reading your article. But wanna remark on few general things, The website
style is perfect, the articles is really great : D.
Good job, cheers
Very great post. I simply stumbled upon your blog and wanted to mention that I’ve truly enjoyed browsing your weblog
posts. In any case I will be subscribing to your feed and I
hope you write once more very soon! Feel free to surf to my page; nhl coins (Johnny)
Does your internet site have the get in touch
with webpage? I’m experiencing difficulty finding it however, I would like to give you an email.
I’ve received a few ideas for your weblog you are interested
in hearing. In either case, fantastic site and I also
anticipate witnessing it enhance with time. Also visit my web page: dating local
Hi there! This is my first comment here so I just wanted to give a quick shout out and say I genuinely enjoy reading your blog posts. Can you recommend any other blogs/websites/forums that
go over the same topics? Thanks a lot! Review my page — cheap csgo skins (Tammy)
For the reason that the admin of this site is working, no
uncertainty very rapidly it will be renowned, due to its quality contents. Feel free to surf to my homepage … nba live coins free — Ara -
After I initially left a comment I appear to have clicked the -Notify
me when new comments are added- checkbox and now each time
a comment is added I get 4 emails with the exact same comment.
There has to be a way you are able to remove me from
that service? Thanks a lot! Feel free to visit my blog … madden 17 coins ps4
Hello to all, the contents present at this website are truly remarkable for people experience, well, keep up the
nice work fellows.
An outstanding share! I have just forwarded this onto a co-worker who has been doing a little homework on this.
And he in fact ordered me dinner simply because I
found it for him… lol. So let me reword this….
Thanks for the meal!! But yeah, thanx for spending the
time to talk about this matter here on your web site.
I feel this is among the so much vital information for me.
And i’m glad reading your article. But want to statement on few common things, The site taste
is wonderful, the articles is actually nice : D. Excellent task, cheers
Nice blog right here! Also your web site rather a lot up fast!
What host are you the use of? Can I am getting your associate link for your host?
I wish my website loaded up as quickly as yours lol Feel free to surf to my webpage — cheap nba live coins (Joeann)
Fantastic items from you, man. I have consider your stuff prior to and you are just too magnificent.
I actually like what you’ve obtained right here, really like what you’re stating
and the best way by which you assert it. You’re making it entertaining and you continue to take care of to stay it smart.
I can’t wait to read much more from you. That
is actually a tremendous site. My website; madden mobile coins
I constantly spent my half an hour to read this weblog’s posts daily along with a cup
of coffee. My web page; buy mink lashes
I am curious to find out what blog platform you happen to be working with?
I’m experiencing some minor security issues with my latest site and I would
like to find something more secure. Do you have any suggestions? Have a look at my web page: csgo skins
Thank you for any other informative website. The place else could I am getting that
kind of information written in such an ideal way? I’ve
a mission that I’m simply now running on, and I’ve been at the look out for such
info. Look into my web-site :: buy nhl 17 coins
There is a lot to discover more about this specific subject matter.
I really like all factors you have produced. Feel free to visit my web page; skype sex
What is actually up, without a doubt this particular
article can genuinely good and that I have learned significant
issues from it regarding blogging. cheers. Review my webpage; free local hookup sites
Merely consider approaches at such as governmental, social
protection networking sites, third party wide range spectrum test team that will be exactly what I merely tipped the iceberg here,
and high returns after a while is obviously easily accessible.
They have been in a position to produce. Of course, it surely takes at fb, Twitter or even LinkedIn. Also visit my website — dating for you
whoah this blog is fantastic i like reading your posts.
Stay up the good work! You understand, a lot of persons are searching round for this information, you
can aid them greatly. Look at my web blog cheap nba live coins (Flynn)
These are actually fantastic ideas in on the topic of blogging. You have touched some pleasant points here.
Any way keep up wrinting. Here is my homepage … h1z1 skins (toxicskies.co)
эро­ти­че­ское пор­но
He or she is carrying out every thing the guy can easily to make the games less dangerous. ESPN Fantasy baseball 2010 is actually the cellular software from ESPN
recreations middle. Review my webpage … http://Lathie.senerew.com/
Hello there, I found your web site by means of Google while searching for a similar matter, your website came up, it seems great. I have bookmarked it in my google bookmarks.
Hi there, simply changed into alert to your weblog through Google, and located that it is truly informative.
I’m going to be careful for brussels. I will appreciate in the event you proceed this in future. A lot of other folks might be benefited from your writing.
Cheers! Feel free to surf to my web page … cheap pubg items
Hello, excellent article. There’s a concern along with your site inside internet explorer, may
experiment this particular? IE nevertheless is the market commander and also a huge component to people will
skip their superb publishing because of this challenge. My page — free sex websites
This post will help the internet visitors for setting up new weblog or even a weblog from start to end. Also visit my blog post: cheap fut 18 coins (leafro.de)
Appreciate this post. Let me try it out. Here is my blog post; buy fifa 18 coins (main.dizayndeniz.com)
Hi there exceptional website! Does running a
blog like this take a great deal of work? I have no understanding of computer programming
but I was hoping to start my own blog in the near future.
Anyway, should you have any recommendations or tips for new blog owners please share.
I understand this is off topic however I just had to ask.
Appreciate it! Here is my blog post buy h1z1 skins
I really like your blog.. very nice colors & theme.
Did you create this website yourself or did you hire someone to do it
for you? Plz respond as I’m looking to design my own blog and would
like to find out where u got this from. thanks Here is my page — buy nba live coins
I made use of the Mother’s gloss as well as the azure Formula polish on my shiny aluminum rims
and that I think the actual azure miracle shine does a significantly better task.
s coming from Wolfsburg creating it all their particular ways, the French chose to
need them about together with the nineteen eighty. My webpage — meet site
Tarot using the internet tirage tarot divinatoire amour gratuit Feel free to visit my web site :: free hook up
Howdy! I understand this is kinda off topic
but I became wanting to know if you know where I could see the best captcha plug-in with regard to my comment form?
I am using the same writings program since your own website and I am having troubles discovering a single?
Thank you! Here is my web blog facebook sex 2016
I am actually thankful to the owner of this site
who has shared this enormous piece of writing at here. Here is my web page … cheap nba live coins, Jeannine,
I know this site gives quality based articles
or reviews and other data, is there any other site which provides these information in quality? Here is my weblog; cheap fut 18 coins
Today, I went to the beach with my children. I found a sea shell
and gave it to my 4 year old daughter and said «You can hear the ocean if you put this to your ear.»
She placed the shell to her ear and screamed. There was
a hermit crab inside and it pinched her ear. She never
wants to go back! LoL I know this is entirely
off topic but I had to tell someone! Also visit my page — mink eyelashes
Its like you read my mind! You seem to know so much about this, like you
wrote the book in it or something. I think that you can do with a
few pics to drive the message home a little bit, but instead of that, this is excellent blog.
A fantastic read. I’ll definitely be back. Take a look at my webpage — cheap nba mobile coins (Audrea)
It’s going to be end of mine day, however before finish I am reading this wonderful article to increase my knowledge. Here is my web page — madden 17 coins (http://omid.farhangsara.ir/Default.aspx?TabId=1647&UserID=374904)
It’s really a cool and useful piece of info. I’m glad
that you just shared this useful information with us.
Please keep us informed like this. Thanks for sharing. My web blog csgo skins for sale cheap
Your style is unique in comparison to other people I’ve read stuff from.
Many thanks for posting when you’ve got the opportunity,
Guess I will just bookmark this page.
Hi, just wanted to mention, I enjoyed this article. It was inspiring.
Keep on posting!
I wanted to thank you for this wonderful read!!
I certainly loved every bit of it. I’ve got you book-marked
to check out new stuff you post…
Nice answer back in return of this issue with genuine arguments and telling everything regarding that.
I was able to find good information from your blog posts.
For most up-to-date information you have to pay a quick
visit world wide web and on world-wide-web I found this
website as a finest site for most up-to-date updates.
Ahaa, its nice dialogue on the topic of this post at this place at this website,
I have read all that, so at this time me also commenting here.
Hi there! This is my first comment here so I
just wanted to give a quick shout out and say I truly enjoy
reading your articles. Can you recommend any other blogs/websites/forums that deal with the same topics?
Thanks for your time!
Very nice post. I just stumbled upon your blog and
wished to say that I’ve really enjoyed browsing your blog posts. In any case I will be subscribing to your rss feed and I hope you
write again soon!
I always spent my half an hour to read this website’s content daily along with a
cup of coffee.
An interesting discussion is definitely worth comment. I do believe that you should publish more on this topic,
it might not be a taboo subject but generally people don’t talk about these issues. To the next! Best wishes!!
I pay a quick visit each day a few web pages and websites
to read articles or reviews, but this blog gives quality based content.
Please let me know if you’re looking for a author for your site.
You have some really great posts and I feel I would be a good asset.
If you ever want to take some of the load off, I’d absolutely love
to write some material for your blog in exchange
for a link back to mine. Please shoot me an email if interested.
Cheers!
I’m sure this in the event that off subject but
i am appearing in to beginning my own weblog and was curious just what all is required
to get build?
I have been surfing online more than 3 hours as of late,
yet I by no means discovered any attention-grabbing article
like yours. It’s beautiful worth sufficient for me. In my view, if all webmasters and
bloggers made just right content as you probably did, the
internet might be much more useful than ever before.
Very rapidly this website will be famous among all blogging and site-building users, due to it’s fastidious articles or reviews
Heya i am for the primary time here. I found this board and I find It really useful & it helped
me out much. I hope to give something back and aid others such as you aided
me.
Two entertaining Gothic female costumes tends to be the Cheerless chief therefore the medieval Bride.
Get an electronic camera, obtain a particular if you don’t have a
particular, and also get an image of your self at your desk, looking unfortunate plus discouraged. You can even request guidance from good friends plus people in your family since it is better to have more
than a single thoughts. They cannot generate close work-out pets, a lot more
like great couch potato dogs. Numerous games in or maybe above $40 give no,
set, or maybe terrible multiplayer experience.
Hi, I really do believe it is an outstanding
websites. we stumbledupon information technology ; ) I’ll revisit yet
again because we reserve designated that. Cash and also freedom is the best option to
change, might you getting rich as well as continue to advise
other people.
Only wanna input on couple of basic strategies, the
web site style and design is perfect, the content material is really fantastic : D. Feel free to surf to my webpage date mature women
I had previously been able to find reliable information out of your blog reports. Feel free to surf to my web page facebook sex 2016
I would like to express my own love to suit
your kindness for women exactly who need to have guidance on this
specific research. Your own special dedication to
having the information all around was incredibly helpful and get often allowed
those similar to me to understand her plans. The actual cozy plus useful report implies a whole
lot for me and even more in order to my own office employees.
Thanks a lot; coming from each of us.
youtube filmpje bekijken…
The place to take into consideration the best series and also theaters is
«That cycle» that is the downtown room and the place to find the particular Chicago theater,
Ford middle when it comes down to Performing Arts Oriental theatre, will Cadillac residence theater, that the financial of America theater, therefore the Goodman Theatre. The situation within Niagara Falls has photo as well as summaries of a lot types
of business registers such as these curiosities because the community.
It’s to be directed by simply Rondell Sheridan coming from «which is very Raven» plus «Corey at home».
What is up everyone, it’s my own first go to at the web site, and also piece of crafting will be really fruitful inside help to me personally,
keep pace publishing these types of content.
Great post however I found myself willing to know if you could compose a litte much more about this subject matter? I’d getting really thankful if you may elaborate
a bit more. Many thanks!
Hi to every 1, it really is honestly a soothing for me
to pay a visit this particular website, that it is constructed of priceless Facts.
Appreciating the time as well as stamina you add in the web site along with degree ideas you present. It is great to encounter the weblog every once in a while that
is not exactly the same from date rehashed facts.
Great study! I have bookmarked your site as well as I’m including the RSS feeds to my Google accounts.
cut costs although avoiding the applying of damaging as well as toxic chemical.
Cleansing is very close in order to godliness,
therefore everything needs to be held thoroughly clean. In addition they accomplish
remedial surgical treatment on gums plus supporting limbs
to aid solution gum disorders.
Excellent write-up, what I was wanting.

Оставить отзыв

Жёлтые поля обязательны к заполнению

   

Можете использовать теги <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang=""> <div class=""> <span class=""> <br>