Julia: Regression with arrays of singletons

Created on 9 Feb 2018  路  4Comments  路  Source: JuliaLang/julia

versioninfo()
#Julia Version 0.6.2
#Commit d386e40 (2017-12-13 18:08 UTC)
using BenchmarkTools
struct foo end
V=Vector{foo}(1000_000);
@btime map(identity, V);
#  612.019 锟斤拷s (2 allocations: 96 bytes)
f(::foo)=foo();
VV=similar(V);
@btime VV .= f.(V);
#  311.835 ns (3 allocations: 64 bytes)

Now:

versioninfo()
#Julia Version 0.7.0-DEV.3736
#Commit 4b1cf22f98* (2018-02-06 16:41 UTC)
struct foo end
V=Vector{foo}(1000_000);
@btime map(identity, V);
#  33.398 ms (999491 allocations: 15.25 MiB)
f(::foo)=foo();
VV=similar(V);
@btime VV .= f.(V);
#  32.296 ms (999489 allocations: 15.25 MiB)

This example is not as silly as it seems because we pay for the allocs when broadcasting / mapping over Union{bits,Missing}. In fact I stumbled on this when reading https://github.com/JuliaLang/julia/pull/25924. Annoting @Base.pure does not help.

codegen performance regression

Most helpful comment

Looks like a return statement got indented wrong in the stack:

V=Vector{Nothing}(1000_000);
@code_llvm Base.collect_to!(V, (identity(x) for x in V), 1, 1);
diff --git a/src/codegen.cpp b/src/codegen.cpp
index b3474c4e83..e7c90c281d 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -2115,9 +2115,9 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
                                         !isboxed ? tbaa_arraybuf : tbaa_ptrarraybuf,
                                         data_owner, 0);
                         }
-                        *ret = ary;
-                        return true;
                     }
+                    *ret = ary;
+                    return true;
                 }
             }
         }

All 4 comments

Re changed title: Not entirely sure this is really array related.

#0.6
@code_llvm f(foo)

define void @julia_f_63376() #0 !dbg !5 {
top:
  ret void
}

#0.7
@code_llvm f(foo())

define nonnull %jl_value_t addrspace(10)* @japi1_f_61967(%jl_value_t addrspace(10)*, %jl_value_t addrspace(10)**, i32) #0 {
top:
  %3 = alloca %jl_value_t addrspace(10)**, align 8
  store volatile %jl_value_t addrspace(10)** %1, %jl_value_t addrspace(10)*** %3, align 8
  ret %jl_value_t addrspace(10)* addrspacecast (%jl_value_t* inttoptr (i64 139711532500760 to %jl_value_t*) to %jl_value_t addrspace(10)*)
}

You see the same for e.g. sin(missing) et al.

Looks like a return statement got indented wrong in the stack:

V=Vector{Nothing}(1000_000);
@code_llvm Base.collect_to!(V, (identity(x) for x in V), 1, 1);
diff --git a/src/codegen.cpp b/src/codegen.cpp
index b3474c4e83..e7c90c281d 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -2115,9 +2115,9 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
                                         !isboxed ? tbaa_arraybuf : tbaa_ptrarraybuf,
                                         data_owner, 0);
                         }
-                        *ret = ary;
-                        return true;
                     }
+                    *ret = ary;
+                    return true;
                 }
             }
         }

So should that patch be applied?

Yes.

Was this page helpful?
0 / 5 - 0 ratings