# Custom Type for lazy kernel operations on AbstractArrays, ho can i improve it?

**URL:** <https://discourse.julialang.org/t/custom-type-for-lazy-kernel-operations-on-abstractarrays-ho-can-i-improve-it/35764>\
**Category:** Performance\
**Tags:** question\
**Created:** [March 9, 2020, 6:21pm UTC](https://discourse.julialang.org/t/custom-type-for-lazy-kernel-operations-on-abstractarrays-ho-can-i-improve-it/35764 "2020-03-09T18:21:56Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![francesco.alemanno](https://avatars.discourse-cdn.com/v4/letter/f/e8c25b/32.png) [@francesco.alemanno](https://discourse.julialang.org/u/francesco.alemanno)\
**Post date:** [March 9, 2020, 6:21pm UTC](https://discourse.julialang.org/t/custom-type-for-lazy-kernel-operations-on-abstractarrays-ho-can-i-improve-it/35764/1 "2020-03-09T18:21:56Z")

</div>

Hi guys is there any way to make this performant? it looks like a super useful type see Example of usage

# Type Definition

```julia
struct KernelOp{T,N,S} <: AbstractArray{T,N}
    parent::S
    op::Function
    opdims::CartesianIndex{N}
    lowbound::CartesianIndex{N}
    upbound::CartesianIndex{N}
    @inline function KernelOp{T,N,S}(A::S,operation::Function,dims::CartesianIndex{N}) where {T,N,S <: AbstractArray{T,N}}
        l=minimum(CartesianIndices(A))
        h=maximum(CartesianIndices(A))
        new(A,operation,dims,l,h)
    end
end
@inline function KernelOp(A::AbstractArray{T,N},op::Function,dims::NTuple{N,Int}) where {T,N}
    KernelOp{eltype(A),ndims(A),typeof(A)}(A,op,CartesianIndex(dims))
end
import Base.size, Base.getindex, Base.IndexStyle

@inline IndexStyle(::KernelOp) = IndexCartesian()
@inline function size_parent(A::KernelOp)
    size(A.parent)
end
@inline function size(A::KernelOp)
    return size_parent(A)
end
@inline function getindex(A::KernelOp{T,N,S},Index::Vararg{Int,N}) where {T,N,S}
    I=CartesianIndex(Index)
    @boundscheck checkbounds(A,I)
    @inbounds begin
        lowI=max(I-A.opdims,A.lowbound)
        upI=min(I+A.opdims,A.upbound)
        return A.op(A.parent,lowI:upI,I)
    end
end

```

# Example

take a julia array, mean filter it (f1),  
take maximum filter of the mean filtered array (f2) then compare for equality f1 and f2

```julia
@inline function op_mean(A,r,c)
    m=zero(eltype(A))
    @inbounds begin
        @simd for i in r
            m+=A[i]
        end
    end
    m/length(r)
end
@inline function op_max(A,r,c)
    m=A[r[1]]
    @inbounds begin
        @simd for i in r
            m=max(m,A[i])
        end
    end
    m
end

M=rand(1000,1000)
f1=KernelOp(M,op_mean,(1,1))
f2=KernelOp(f1,op_max,(2,2))

f1.==f2 # here all the computations happen, but it allocates a lot even though it doesnt build explicit copies of the original array

```

to me this looks super beautiful, but unfortunately it allocates a lot, i would like some advice on making it more performant

---

<div class="post-metadata">

**Author:** ![favba](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/favba/32/2735_2.png) [@favba](https://discourse.julialang.org/u/favba)\
**Post date:** [March 9, 2020, 6:36pm UTC](https://discourse.julialang.org/t/custom-type-for-lazy-kernel-operations-on-abstractarrays-ho-can-i-improve-it/35764/2 "2020-03-09T18:36:23Z")

</div>

I haven’t tested it and I’m taking a guess, but I suspect you want your `op` to be concretely typed (`Function` is abstract).  
Why don’t you try defining the struct as following:

```julia
struct KernelOp{T,N,S,F<:Function} <: AbstractArray{T,N}
    parent::S
    op::F
    opdims::CartesianIndex{N}
    lowbound::CartesianIndex{N}
    upbound::CartesianIndex{N}
    @inline function KernelOp{T,N,S}(A::S,operation::Function,dims::CartesianIndex{N}) where {T,N,S <: AbstractArray{T,N}}
        l=minimum(CartesianIndices(A))
        h=maximum(CartesianIndices(A))
        new{T,N,S,typeof(operation)}(A,operation,dims,l,h)
    end
end

```

---

<div class="post-metadata">

**Author:** ![francesco.alemanno](https://avatars.discourse-cdn.com/v4/letter/f/e8c25b/32.png) [@francesco.alemanno](https://discourse.julialang.org/u/francesco.alemanno)\
**Post date:** [March 9, 2020, 7:24pm UTC](https://discourse.julialang.org/t/custom-type-for-lazy-kernel-operations-on-abstractarrays-ho-can-i-improve-it/35764/3 "2020-03-09T19:24:08Z")

</div>

I will try very soon thanks 🙂

---

<div class="post-metadata">

**Author:** ![francesco.alemanno](https://avatars.discourse-cdn.com/v4/letter/f/e8c25b/32.png) [@francesco.alemanno](https://discourse.julialang.org/u/francesco.alemanno)\
**Post date:** [March 9, 2020, 8:05pm UTC](https://discourse.julialang.org/t/custom-type-for-lazy-kernel-operations-on-abstractarrays-ho-can-i-improve-it/35764/4 "2020-03-09T20:05:01Z")

</div>

> **[GitHub - francescoalemanno/KernelOps.jl: Apply lazy kernel operations on...](https://github.com/francescoalemanno/KernelOps.jl)**
>
> Apply lazy kernel operations on AbstractArrays, they are composable and non copying. Have Fun! - GitHub - francescoalemanno/KernelOps.jl: Apply lazy kernel operations on AbstractArrays, they are co...

it worked!
