Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimization pass #58

Merged
merged 48 commits into from
Nov 12, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
d870aa6
Parallelized and optimized corner response calculation.
ljubobratovicrelja Sep 29, 2016
daf4e92
Refactoring of extractCorners.
ljubobratovicrelja Oct 1, 2016
958f5a9
Refactoring rgb(bgr)2gray.
ljubobratovicrelja Oct 1, 2016
b6ac069
Refactoring rgb2hsv.
ljubobratovicrelja Oct 1, 2016
7da0159
Refactoring hsv2rgb.
ljubobratovicrelja Oct 1, 2016
5658eb9
uninitializedArray --> uninitializedSlice.
ljubobratovicrelja Oct 1, 2016
0fc5b01
Refactoring yuv2rgb, overall module cleanup.
ljubobratovicrelja Oct 1, 2016
5970cb2
Added static slice packing helpers.
ljubobratovicrelja Oct 2, 2016
720fd50
Extracted ndIter kernel lambdas to functions.
ljubobratovicrelja Oct 2, 2016
21f6118
div by 100.0 replaced with mul by 0.01.
ljubobratovicrelja Oct 2, 2016
c3cb076
Extracted kernels to functions, added fastmath.
ljubobratovicrelja Oct 2, 2016
5611394
Replaced std.math.sqrt with llvm_sqrt.
ljubobratovicrelja Oct 2, 2016
deaeed9
Added mcpu=native flag.
ljubobratovicrelja Oct 2, 2016
e5228ed
Randomized hsv values.
ljubobratovicrelja Oct 2, 2016
aead0ad
Loop refactoring.
ljubobratovicrelja Oct 2, 2016
09b5f1f
Fixed non-contiguous loop iteration fail.
ljubobratovicrelja Oct 2, 2016
444f13a
Added nothrow and nogc.
ljubobratovicrelja Oct 6, 2016
e4075f1
Refactoring of convolution functions.
ljubobratovicrelja Oct 6, 2016
a486d08
Merge branch 'master' into optimization-patch-2
ljubobratovicrelja Oct 9, 2016
a58eb04
Merge branch 'master' into optimization-patch-2
ljubobratovicrelja Oct 10, 2016
7ab3a0b
Added tensor border extraction.
ljubobratovicrelja Oct 11, 2016
f352a77
Added in contract for non-matrix tensors.
ljubobratovicrelja Oct 11, 2016
4a9722a
Reorganized templates in boundary conditions to support lazy tensors.
ljubobratovicrelja Oct 11, 2016
6a1023e
Temporary silence of isBoundaryCondition.
ljubobratovicrelja Oct 11, 2016
66367dc
Refactoring of bilateralFilter function.
ljubobratovicrelja Oct 11, 2016
56d1ede
Tweaks in bilateralDisparityFilter to match bilateralFilter changes.
ljubobratovicrelja Oct 11, 2016
a87f2bd
Tweaks in bilateralFilter tests to match bilateralFilter changes.
ljubobratovicrelja Oct 11, 2016
549cbab
Fixed multi-channel bilateralFilter.
ljubobratovicrelja Oct 11, 2016
539aced
Reorganized convolution templates to support lazy tensors.
ljubobratovicrelja Oct 11, 2016
13fc0b6
Adopted convolution changes in benchmark functions.
ljubobratovicrelja Oct 11, 2016
ecc4b0e
Refactoring of calcGradient, calcPartialDerivatives.
ljubobratovicrelja Oct 18, 2016
4569ffb
Refactoring of nonMaximaSuppression.
ljubobratovicrelja Oct 18, 2016
7f2f5b7
Refactored scaled and ranged to accept lazy tensors.
ljubobratovicrelja Oct 18, 2016
2cd6343
Parallelized calcPartialDerivatives, calcGradients and canny.
ljubobratovicrelja Oct 19, 2016
49a6963
Fixed docs typo.
ljubobratovicrelja Oct 19, 2016
ba7b6ac
Merge branch 'master' into optimization-patch-2
ljubobratovicrelja Nov 3, 2016
1d2b8e4
Merge branch 'master' into optimization-patch-2
ljubobratovicrelja Nov 3, 2016
b21c660
Refactoring of filterNonMaximum.
ljubobratovicrelja Nov 4, 2016
664a58f
Docs fixup.
ljubobratovicrelja Nov 4, 2016
fcd1ede
filterNonMaximum optimization.
ljubobratovicrelja Nov 4, 2016
b83ae5a
Added type check for filterNonMaximum input.
ljubobratovicrelja Nov 5, 2016
c42e8fd
Refactoring of warp/remap.
ljubobratovicrelja Nov 10, 2016
0a83b39
Added fastmath on linear interpolation.
ljubobratovicrelja Nov 10, 2016
24e8fbb
Updated function template arguments.
ljubobratovicrelja Nov 10, 2016
0c744a7
Refactoring of threshold.
ljubobratovicrelja Nov 10, 2016
7774f26
Fixed fastmath floor.
ljubobratovicrelja Nov 11, 2016
824a4a8
Merge with master.
ljubobratovicrelja Nov 11, 2016
d88c786
Docs and formatting, asserts and notes on contiguous slice request.
ljubobratovicrelja Nov 12, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 29 additions & 12 deletions source/dcv/core/algorithm.d
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,21 @@ import std.traits : isNumeric, isFloatingPoint;
import mir.ndslice.slice : Slice, sliced, DeepElementType;
import mir.ndslice.algorithm : ndReduce, ndEach, Yes;

import dcv.core.utils : isSlice;

version(LDC)
{
import ldc.intrinsics : sqrt = llvm_sqrt, fabs = llvm_fabs, min = llvm_minnum, max = llvm_maxnum;
import ldc.intrinsics : sqrt = llvm_sqrt, fabs = llvm_fabs;
}
else
{
import std.math : sqrt, fabs;
import std.algorithm.comparison : min, max;
}

version(unittest)
{
import std.math : approxEqual;
import ldc.intrinsics : min = llvm_minnum, max = llvm_maxnum;
}

/**
Expand Down Expand Up @@ -170,10 +172,14 @@ Returns:
Scaled input tensor.

*/
@nogc nothrow auto scaled(Scalar, Range, size_t N)(auto ref Slice!(N, Range) tensor, Scalar alpha = 1, Scalar beta = 0)
if (isNumeric!Scalar)
nothrow @nogc auto scaled(Scalar, Tensor)(Tensor tensor, Scalar alpha = 1, Scalar beta = 0) if (isNumeric!Scalar)
in
{
static assert(isSlice!Tensor, "Input tensor has to be of type mir.ndslice.slice.Slice.");
}
body
{
tensor.ndEach!((ref v) { v = alpha * (v) + beta; }, Yes.vectorized);
tensor.ndEach!((ref v) { v = cast(DeepElementType!Tensor)(alpha * (v) + beta); }, Yes.vectorized);
return tensor;
}

Expand All @@ -198,21 +204,32 @@ Params:
maxValue = Maximal value output tensor should contain.

*/
@nogc auto ranged(Scalar, Range, size_t N)(auto ref Slice!(N, Range) tensor,
nothrow @nogc auto ranged(Scalar, Tensor)(Tensor tensor,
Scalar minValue = 0, Scalar maxValue = 1) if (isNumeric!Scalar)
in
{
static assert(isSlice!Tensor, "Input tensor has to be of type mir.ndslice.slice.Slice.");
}
body
{
alias RangeElementType = DeepElementType!(typeof(tensor));
alias T = DeepElementType!Tensor;

auto _min = ndReduce!(min, Yes.vectorized)(RangeElementType.max, tensor);
static if (isFloatingPoint!RangeElementType)
auto _max = ndReduce!(max, Yes.vectorized)(RangeElementType.min_normal, tensor);
static if (isFloatingPoint!T)
{
import ldc.intrinsics : min = llvm_minnum, max = llvm_maxnum;
auto _max = ndReduce!(max, Yes.vectorized)(T.min_normal, tensor);
}
else
auto _max = ndReduce!(max, Yes.vectorized)(RangeElementType.min, tensor);
{
import std.algorithm.comparison : min, max;
auto _max = ndReduce!(max, Yes.vectorized)(T.min, tensor);
}

auto _min = ndReduce!(min, Yes.vectorized)(T.max, tensor);
auto rn_val = _max - _min;
auto sc_val = maxValue - minValue;

tensor.ndEach!((ref a) { a = sc_val * ((a - _min) / rn_val) + minValue; }, Yes.vectorized);
tensor.ndEach!((ref a) { a = cast(T)(sc_val * ((a - _min) / rn_val) + minValue); }, Yes.vectorized);

return tensor;
}
Expand Down
148 changes: 109 additions & 39 deletions source/dcv/core/utils.d
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,77 @@ static Slice!(N, V*) emptySlice(size_t N, V)() pure @safe nothrow
return Slice!(N, V*)();
}

package(dcv) @nogc pure nothrow
{
/**
Pack and unpack (N, T*) slices to (N-1, T[M]*).
*/
auto staticPack(size_t CH, size_t N, T)(Slice!(N, T*) slice)
{
ulong[N-1] shape = slice.shape[0 .. N-1];
long[N-1] strides = [slice.structure.strides[0] / CH, slice.structure.strides[1] / CH];
T[CH]* ptr = cast(T[CH]*)slice.ptr;
return Slice!(N-1, T[CH]*)(shape, strides, ptr);
}

/// ditto
auto staticUnpack(size_t CH, size_t N, T)(Slice!(N, T[CH]*) slice)
{
ulong[N+1] shape = [slice.shape[0], slice.shape[1], CH];
long[N+1] strides = [slice.structure.strides[0] * CH, slice.structure.strides[1] * CH, 1];
T* ptr = cast(T*)slice.ptr;
return Slice!(N+1, T*)(shape, strides, ptr);
}

@safe @nogc nothrow pure auto borders(Shape)(Shape shape, size_t ks)
in
{
static assert(Shape.length == 2, "Non-matrix border extraction is not currently supported.");
}
body
{
import std.typecons : Tuple;
import std.algorithm.comparison : max;
import std.range : iota;
import std.traits : ReturnType;

struct Range(Iota)
{
Iota rows;
Iota cols;
@disable this();
this(Iota rows, Iota cols)
{
this.rows = rows;
this.cols = cols;
}
}

auto range(Iota)(Iota rows, Iota cols)
{
return Range!Iota(rows, cols);
}

// forced size_t cast...
auto _iota(B, E, S)(B begin, E end, S step = 1)
{
return iota(size_t(begin), size_t(end), size_t(step));
}

size_t kh = max(1, ks / 2);
alias Iota = ReturnType!(iota!(size_t, size_t, size_t));

Range!(Iota)[4] borders = [
range(_iota(0, shape[0]), _iota(0, kh)),
range(_iota(0, shape[0]), _iota(shape[1] - kh, shape[1])),
range(_iota(0, kh), _iota(0, shape[1])),
range(_iota(shape[0] - kh, shape[0]), _iota(0, shape[1]))
];

return borders;
}
}

/**
Take another typed Slice. Type conversion for the Slice object.

Expand Down Expand Up @@ -185,43 +256,39 @@ static if (__VERSION__ >= 2071)
/// Check if given function can perform boundary condition test.
template isBoundaryCondition(alias bc)
{
import std.typetuple;
enum bool isBoundaryCondition = true;
}

nothrow @nogc pure
{

alias Indices = TypeTuple!(int, int);
alias bct = bc!(2, float, Indices);
static if (isCallable!(bct) && is(Parameters!bct[0] == Slice!(2, float*))
&& is(Parameters!bct[1] == int) && is(Parameters!bct[2] == int) && is(ReturnType!bct == float))
/// $(LINK2 https://en.wikipedia.org/wiki/Neumann_boundary_condition, Neumann) boundary condition test
auto neumann(Tensor, Indices...)(Tensor tensor, Indices indices)
if (isSlice!Tensor && allSameType!Indices && allSatisfy!(isIntegral, Indices))
{
enum bool isBoundaryCondition = true;
immutable N = ReturnType!(Tensor.shape).length;
static assert(indices.length == N, "Invalid index dimension");
return tensor.bcImpl!_neumann(indices);
}
else

/// $(LINK2 https://en.wikipedia.org/wiki/Periodic_boundary_conditions,Periodic) boundary condition test
auto periodic(Tensor, Indices...)(Tensor tensor, Indices indices)
if (isSlice!Tensor && allSameType!Indices && allSatisfy!(isIntegral, Indices))
{
enum bool isBoundaryCondition = false;
immutable N = ReturnType!(Tensor.shape).length;
static assert(indices.length == N, "Invalid index dimension");
return tensor.bcImpl!_periodic(indices);
}
}

/// $(LINK2 https://en.wikipedia.org/wiki/Neumann_boundary_condition, Neumann) boundary condition test
ref T neumann(size_t N, T, Indices...)(ref Slice!(N, T*) slice, Indices indices)
if (allSameType!Indices && allSatisfy!(isIntegral, Indices))
{
static assert(indices.length == N, "Invalid index dimension");
return slice.bcImpl!_neumann(indices);
}

/// $(LINK2 https://en.wikipedia.org/wiki/Periodic_boundary_conditions,Periodic) boundary condition test
ref T periodic(size_t N, T, Indices...)(ref Slice!(N, T*) slice, Indices indices)
if (allSameType!Indices && allSatisfy!(isIntegral, Indices))
{
static assert(indices.length == N, "Invalid index dimension");
return slice.bcImpl!_periodic(indices);
}
/// Symmetric boundary condition test
auto symmetric(Tensor, Indices...)(Tensor tensor, Indices indices)
if (isSlice!Tensor && allSameType!Indices && allSatisfy!(isIntegral, Indices))
{
immutable N = ReturnType!(Tensor.shape).length;
static assert(indices.length == N, "Invalid index dimension");
return tensor.bcImpl!_symmetric(indices);
}

/// Symmetric boundary condition test
ref T symmetric(size_t N, T, Indices...)(ref Slice!(N, T*) slice, Indices indices)
if (allSameType!Indices && allSatisfy!(isIntegral, Indices))
{
static assert(indices.length == N, "Invalid index dimension");
return slice.bcImpl!_symmetric(indices);
}

/// Alias for generalized boundary condition test function.
Expand Down Expand Up @@ -264,30 +331,33 @@ unittest

private:

ref auto bcImpl(alias bcfunc, size_t N, T, Indices...)(ref Slice!(N, T*) slice, Indices indices)
nothrow @nogc pure:

auto bcImpl(alias bcfunc, Tensor, Indices...)(Tensor tensor, Indices indices)
{
immutable N = ReturnType!(Tensor.shape).length;
static if (N == 1)
{
return slice[bcfunc(cast(int)indices[0], cast(int)slice.length)];
return tensor[bcfunc(cast(int)indices[0], cast(int)tensor.length)];
}
else static if (N == 2)
{
return slice[bcfunc(cast(int)indices[0], cast(int)slice.length!0),
bcfunc(cast(int)indices[1], cast(int)slice.length!1)];
return tensor[bcfunc(cast(int)indices[0], cast(int)tensor.length!0),
bcfunc(cast(int)indices[1], cast(int)tensor.length!1)];
}
else static if (N == 3)
{
return slice[bcfunc(cast(int)indices[0], cast(int)slice.length!0),
bcfunc(cast(int)indices[1], cast(int)slice.length!1), bcfunc(cast(int)indices[2],
cast(int)slice.length!2)];
return tensor[bcfunc(cast(int)indices[0], cast(int)tensor.length!0),
bcfunc(cast(int)indices[1], cast(int)tensor.length!1), bcfunc(cast(int)indices[2],
cast(int)tensor.length!2)];
}
else
{
foreach (i, ref id; indices)
{
id = bcfunc(cast(int)id, cast(int)slice.shape[i]);
id = bcfunc(cast(int)id, cast(int)tensor.shape[i]);
}
return slice[indices];
return tensor[indices];
}
}

Expand Down
Loading