--minUptime and --spinSleepTime not working in common

Let's use this simple script 'exit.js' that immediately "crashes":
console.log("Script started, exiting with code 1");
process.exit(1);

--minUptime not working
forever --minUptime 500 --spinSleepTime 1000 exit.js

Unless I completely misinterpret the docs, this should:

keep restarting the script if it was running for at least 500ms (which it is not in this case)
When restarting, wait 1000ms between each restart

What actually happens is that it's being restarted forever, although spinSleepTime is respected:
# forever --minUptime 500 --spinSleepTime 1000 exit.js
Starting and exiting with code 1
error: Forever detected script exited with code: 1
error: Script restart attempt #1
Starting and exiting with code 1
error: Forever detected script exited with code: 1
error: Script restart attempt #2
Starting and exiting with code 1
error: Forever detected script exited with code: 1
error: Script restart attempt #3
Starting and exiting with code 1
error: Forever detected script exited with code: 1
…

Running without --spinSleepTime seems to work as intended. it respects the --minUptime option, but restarts immediately when it's exceeded.
--spinSleepTime not working
forever --minUptime 1 --spinSleepTime 1000 exit.js

This allows forever to practically always restart the script, but it does restart it instantly without waiting 1000ms.

I'm using forever v0.15.1.
I tested this with node v0.12.7, iojs v2.5.0, and iojs v3.0.0.

I had the same.

Having same issue. I logged a little bit inside the source and it seems like the code they use to grab the arguments is pretty broken.

+1

same issue, I put 60000 into --spinSleepTime flag, but the script.js launch between 6 sec, which I expect it launch between 60 sec

any solution or work around?

+1 here

+1


Error when closing dropdown when select2 imported as a module

Prerequisites

[x] I have searched for similar issues in both open and closed tickets and cannot find a duplicate
[x] The issue still exists against the latest master branch of Select2
[x] This is not a usage question (Those should be directed to the community)
[x] I have attempted to find the simplest possible steos to reproduce the issue
[ ] I have included a failing test as a pull request (Optional)

Steps to reproduce the issue

Import Select2 as a module, rather than as a jQuery plugin (eg using Webpack):
var Select2 = require('select2')
var $ = require('jquery')

Open a Select2 dropdown

Click outside of the dropdown to close it

Expected behavior and actual behavior
When I follow those steps, I see the error base.js:135 Uncaught TypeError: $element.select2 is not a function in the JS console, and the dropdown stays open.
I was expecting the dropdown to close.
Environment
Browsers

[x] Google Chrome
[x] Mozilla Firefox
[x] Internet Explorer

Operating System

[x] Windows
[ ] Mac OS X
[x] Linux
[ ] Mobile

Libraries

jQuery version: 2.2.2
Select2 version: 4.0.2 (also happens in master)

Isolating the problem

[ ] This bug happens on the examples page
[x] The bug happens consistently across all tested browsers
[x] This bug happens when using Select2 without other pluigns
[ ] I can reproduce this bug in a jsbin

This looks like it's a one-line fix, as soon as I can get the tests to run I'll file a PR.

Triggering events can lead to unintended side effects.  Are you sure this is the only way to handle the issue?

This ticket and PR is nearly two years old, and since Select2 is no longer used on the project I was on when I came across this bug and I no longer work at the company that project was for, I haven't touched Select2 in a long while. So I have no idea, sorry :(

No problem, thanks for letting us know!


@avx in subspace matrix multiplication is much slower than StaticArrays

I was trying to use @avx in the following subspace matrix multiplication code, but to my surprise, LoopVectorization is significantly slower than StaticArrays, I'm not sure if I'm doing it correctly
The subspace matrix multiplication can be defined as the following julia code
function subspace_smm!(st::AbstractMatrix, indices, U::AbstractMatrix, subspace)
    @inbounds @views for k in subspace
        idx = k .+ indices
        for b in 1:size(st, 2)
            st[idx, b] = U * st[idx, b]
        end
    end
    return st
end

where subspace and indices a set of integers to describe the subspace, and U is a matrix in the subspace, the matrix multiplication happens inside the subspace. An example of how to use the above function
using StaticArrays
using BenchmarkTools

n = 3
st = rand(ComplexF64, 1 << 8, 100)
y = similar(st, (1 << n, 100))
U = rand(ComplexF64, 1 << n, 1 << n)
SU = @SMatrix rand(ComplexF64, 1 << n, 1 << n)
indices = [1, 2, 5, 6, 9, 10, 13, 14]
subspace = [0, 2, 16, 18, 32, 34, 48, 50, 64, 66, 80, 82, 96, 98, 112, 114, 128, 130, 144, 146, 160, 162, 176, 178, 192, 194, 208, 210, 224, 226, 240, 242]

julia> @benchmark subspace_smm!($(copy(st)), $indices, $SU, $subspace)
BenchmarkTools.Trial:
  memory estimate:  4.50 KiB
  allocs estimate:  32
  --------------
  minimum time:     89.259 μs (0.00% GC)
  median time:      115.608 μs (0.00% GC)
  mean time:        115.988 μs (0.10% GC)
  maximum time:     1.334 ms (91.20% GC)
  --------------
  samples:          10000
  evals/sample:     1

now if we implement the above matrix multiplication with plain for loop and use @avx, it can be implemented as following
function subspace_mm!(st::AbstractMatrix, indices, U::AbstractMatrix{T}, y::AbstractMatrix, subspace) where T
    @avx for k in subspace
        for b in 1:size(st, 2)
            for i in 1:size(U, 1)
                y[i, b] = zero(T)
                for j in 1:size(U, 2)
                    y[i, b] += U[i, j] * st[k + indices[j], b]
                end
            end

            for i in 1:size(U, 1)
                st[k + indices[i], b] = y[i, b]
            end
        end
    end
    return st
end

however this then become significantly slower than the previous naive version using StaticArrays
julia> y = similar(st, (1 << n, 100))

julia> subspace_mm!($(copy(st)), $indices, $SU, $y, $subspace)
BenchmarkTools.Trial:
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     203.286 μs (0.00% GC)
  median time:      213.306 μs (0.00% GC)
  mean time:        213.945 μs (0.00% GC)
  maximum time:     245.486 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

y above is  a temp mem to store result of each subspace matrix multiplication, so we can assign them back to st. I'm testing this on Ryzen
julia> versioninfo()
Julia Version 1.6.0-DEV.1699
Commit 8a5ac94e96* (2020-12-08 03:24 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: AMD Ryzen 9 3900X 12-Core Processor
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-11.0.0 (ORCJIT, znver2)
Environment:
  JULIA_EDITOR = "/home/roger/.vscode-server/bin/e5a624b788d92b8d34d1392e4c4d9789406efe8f/bin/code"
  JULIA_NUM_THREADS =

I'm not sure if it would be different on an AVX512 available machine, but I guess probably not the AVX512 issue since SA is much faster on the same machine?

and for reference, if we replace the @avx with just @inbounds, and let Julia handle everything, it is a bit faster than @avx
julia> @benchmark BQCESubroutine.subspace_mm!($(copy(st)), $indices, $SU, $temp_st, $subspace)
BenchmarkTools.Trial:
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     185.677 μs (0.00% GC)
  median time:      198.357 μs (0.00% GC)
  mean time:        198.696 μs (0.00% GC)
  maximum time:     217.576 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

This problem actually hits 5 current limitations in LoopVectorization. Which is quite impressive for such simple looking loops.
First of all,
julia> typeof.((st, indices, SU, y, subspace))
(Matrix{ComplexF64}, Vector{Int64}, SMatrix{8, 8, ComplexF64, 64}, Matrix{ComplexF64}, Vector{Int64})

julia> LoopVectorization.check_args(st, indices, SU, y, subspace)
false

This means that LoopVectorization doesn't support the types of arguments you're using. Instead of throwing an error, it applies @inbounds @fastmath and hopes for the best.
It returns false because of two current limitations:

Only supporting primitive element types: Union{Bool, Base.HWReal}. This will probably be solved when making the code parsing/LoopSet construction code take advantage of the compiler tools, so that it can run optimization passes until operations on ComplexF64 are deconstructed into operations on individual Float64.
StaticArrays.SArray aren't supported. StaticArrays.MArray are. The problem with the former is that I can't get a pointer. I've played around with things like Ref(A::SArray), e.g. in the documentation, where I could speed up SMatrix multiplication following that approach, but it still lagged well behind just starting with MArrays in the first place, because the compiler will explicilty copy all the memory for every Ref, even if it is stack allocated, non-mutated memory is marked as invariant, and limited lifetimes marked. I don't know why that doesn't fix it. I've also considered trying to wrap them in a struct to emulate the behavior of a StridedPointer, i.e. createa a SIMD vector via repeated indexing. That will probably work better in many cases for regular vector loads, but I haven't been able to get the compiler to emit things like masked loads this way. Of the four limitations, this would be the easiest to fix, but as performance would still be lacking compared to the alternatives, I haven't put the time in. If you want maximize performance, sticking with the mutable arrays is better. As I demo here, you can make mutable arrays safe, stack allocated, and still pass them through non-inlined function boundaries. Having to use PaddedMatrices.@gc_preserve may not be the most ergonomic thing (and PaddedMatrices itself is lacking many featyures compared to StaticArrays, i.e. basically everything except matmul at the moment [and also doesn't support complex numbers], but I'll at least add things like linear algebra functionality once I address some LoopVectorization limitations).

LoopVectorization.check_args looks for these limitations, and returns true/false depending on whether the arrays are compatible. If false, it'll use a fallback loop which is just the original loop with @inbounds @fastmath.
Which actually makes this a little surprising:

and for reference, if we replace the @avx with just @inbounds, and let Julia handle everything, it is a bit faster than @avx

Because that suggests @inbounds @fastmath is slower than just @inbounds on your machine. I see roughly equivalent times:
function subspace_mm!(st::AbstractMatrix, indices, U::AbstractMatrix{T}, y::AbstractMatrix, subspace) where T
    @avx for k in subspace
        for b in 1:size(st, 2)
            for i in 1:size(U, 1)
                y[i, b] = zero(T)
                for j in 1:size(U, 2)
                    y[i, b] += U[i, j] * st[k + indices[j], b]
                end
            end

            for i in 1:size(U, 1)
                st[k + indices[i], b] = y[i, b]
            end
        end
    end
    return st
end
function subspace_mm_inbounds!(st::AbstractMatrix, indices, U::AbstractMatrix{T}, y::AbstractMatrix, subspace) where T
    @inbounds for k in subspace
        for b in 1:size(st, 2)
            for i in 1:size(U, 1)
                y[i, b] = zero(T)
                for j in 1:size(U, 2)
                    y[i, b] += U[i, j] * st[k + indices[j], b]
                end
            end

            for i in 1:size(U, 1)
                st[k + indices[i], b] = y[i, b]
            end
        end
    end
    return st
end
function subspace_mm_inbounds_fastmath!(st::AbstractMatrix, indices, U::AbstractMatrix{T}, y::AbstractMatrix, subspace) where T
    @inbounds @fastmath for k in subspace
        for b in 1:size(st, 2)
            for i in 1:size(U, 1)
                y[i, b] = zero(T)
                for j in 1:size(U, 2)
                    y[i, b] += U[i, j] * st[k + indices[j], b]
                end
            end

            for i in 1:size(U, 1)
                st[k + indices[i], b] = y[i, b]
            end
        end
    end
    return st
end

This yields
julia> y = similar(st, (1 << n, 100));

julia> @benchmark subspace_mm!($(copy(st)), $indices, $SU, $y, $subspace)
BenchmarkTools.Trial:
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     216.051 μs (0.00% GC)
  median time:      216.350 μs (0.00% GC)
  mean time:        216.578 μs (0.00% GC)
  maximum time:     360.086 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark subspace_mm_inbounds!($(copy(st)), $indices, $SU, $y, $subspace)
BenchmarkTools.Trial:
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     215.090 μs (0.00% GC)
  median time:      216.418 μs (0.00% GC)
  mean time:        216.404 μs (0.00% GC)
  maximum time:     351.244 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark subspace_mm_inbounds_fastmath!($(copy(st)), $indices, $SU, $y, $subspace)
BenchmarkTools.Trial:
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     215.981 μs (0.00% GC)
  median time:      217.641 μs (0.00% GC)
  mean time:        217.920 μs (0.00% GC)
  maximum time:     352.142 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

For reference, I get this on the first benchmark
julia> @benchmark subspace_smm!($(copy(st)), $indices, $SU, $subspace)
BenchmarkTools.Trial:
  memory estimate:  4.50 KiB
  allocs estimate:  32
  --------------
  minimum time:     114.603 μs (0.00% GC)
  median time:      116.125 μs (0.00% GC)
  mean time:        116.681 μs (0.06% GC)
  maximum time:     880.390 μs (79.72% GC)
  --------------
  samples:          10000
  evals/sample:     1

So, how can we work around those two limitations?
Split the complex arrays into the real and imaginary components, and replace SMatrix with MMatrix.
For example:
using StaticArrays, LoopVectorization, BenchmarkTools

n = 3
st = rand(ComplexF64, 1 << 8, 100);
y = similar(st, (1 << n, 100));
U = rand(ComplexF64, 1 << n, 1 << n);
SU = @SMatrix rand(ComplexF64, 1 << n, 1 << n);
indices = [1, 2, 5, 6, 9, 10, 13, 14];
subspace = [0, 2, 16, 18, 32, 34, 48, 50, 64, 66, 80, 82, 96, 98, 112, 114, 128, 130, 144, 146, 160, 162, 176, 178, 192, 194, 208, 210, 224, 226, 240, 242];

function subspace_smm!(st::AbstractMatrix, indices, U::AbstractMatrix, subspace)
    @inbounds @views for k in subspace
        idx = k .+ indices
        for b in 1:size(st, 2)
            st[idx, b] = U * st[idx, b]
        end
    end
    return st
end

function subspace_mm!(
    st_re::AbstractMatrix, st_im::AbstractMatrix,
    indices, U_re::AbstractMatrix{T}, U_im::AbstractMatrix{T}, subspace
) where {T <: Base.HWReal}
    for k in subspace
        @avx unroll=(2,8) for b in axes(st_re, 2)
            for i in axes(U_re, 1)
                y_re= zero(T)
                y_im = zero(T)
                for j in axes(U_re, 2)
                    U_re_i_j = U_re[i,j]
                    U_im_i_j = U_im[i,j]
                    st_re_j_b = st_re[k + indices[j], b]
                    st_im_j_b = st_im[k + indices[j], b]
                    y_re += U_re_i_j * st_re_j_b - U_im_i_j * st_im_j_b
                    y_im += U_re_i_j * st_im_j_b + U_im_i_j * st_re_j_b
                end
                st_re[k + indices[i], b] = y_re
                st_im[k + indices[i], b] = y_im
            end
        end
    end
    return (st_re, st_im)
end

st_re = transpose(real.(transpose(st)));
st_im = transpose(imag.(transpose(st)));
MU_re = MMatrix(real.(SU));
MU_im = MMatrix(imag.(SU));

st2 = subspace_smm!((copy(st)), indices, SU, subspace);
st_re2, st_im2 = subspace_mm!((deepcopy(st_re)), (deepcopy(st_im)), indices, MU_re, MU_im,  subspace);
st_re2 ≈ real.(st2)
st_im2 ≈ imag.(st2)

sindices = SVector(indices...);
@benchmark subspace_smm!($(copy(st)), $sindices, $SU, $subspace)

@benchmark subspace_mm!($(deepcopy(st_re)), $(deepcopy(st_im)), $indices, $MU_re, $MU_im,  $subspace)

Note all those transposes, and the deepcopys in the benchmark in place of copy (copy will createa a regular Array, transposing the memory layout, deepcopy will make a Transpose{T,Array{T,2}} just like the parent).
This is because I want a row-major memory layout.
I want row-major, because column-major st_re[k + indices[i], b] would require accessing discontiguous memory. Successive ks are not necessarilly 1 apart, and indices face the same problem. Either would force using gather and scatter operations to load/store elements, which are much slower than the corresponding contiguous load/stores.
If we tranpose the underlying memory (make the array row-major), then successive bs are indeed contiguous.
Before showing the benchmarks, the other 3 limitations:
3. Currently, LoopVectorization only supports "perfect" loop nests, meaning nesting-doll like loops. Each loop has only 1 or 0 loops inside it. The original @avx code had two for i... loops within the for b... loop.  For some reason I never bothered to make LoopVectorization check for this, so it'll result in undefined behavior. So in the above code, I collapsed those loops together and got rid of the need for y. I've started (slowly) working on a rewrite of LoopVectorization that will address this, allowing there to be multiple loops at each level of the nest. It will also be able to fuse these loops as an optimization.
4. It currently doesn't track dependencies between loop iterations, and assumes they can be reordered arbitrarilly. I'm also addressing that in the rewrite, but it's something to watch out for here, because we're loading from and storing to st_re. I think even after monitoring dependencies, it'll make really aggressive assumptions about indices, i.e. that it can load/store from multiple in parallel without collisions. The answers were right after I moved @avx inside the k loop, instead of outside it, and also manually set unroll=(2,8) to get it to fully unroll i by 8:
julia> U_re = MU_re; U_im = MU_im;

julia> ls = LoopVectorization.@avx_debug for b in axes(st_re, 2)
                   for i in axes(U_re, 1)
                       y_re= zero(T)
                       y_im = zero(T)
                       for j in axes(U_re, 2)
                           U_re_i_j = U_re[i,j]
                           U_im_i_j = U_im[i,j]
                           st_re_j_b = st_re[k + indices[j], b]
                           st_im_j_b = st_im[k + indices[j], b]
                           y_re += U_re_i_j * st_re_j_b - U_im_i_j * st_im_j_b
                           y_im += U_re_i_j * st_im_j_b + U_im_i_j * st_re_j_b
                       end
                       st_re[k + indices[i], b] = y_re
                       st_im[k + indices[i], b] = y_im
                   end
               end;
OPS = Tuple{:numericconstant, Symbol("##zero#823"), LoopVectorization.OperationStruct(0x0000000000000012, 0x0000000000000000, 0x0000000000000003, 0x0000000000000000, LoopVectorization.constant, 0x00, 0x01), :numericconstant, Symbol("##zero#824"), LoopVectorization.OperationStruct(0x0000000000000012, 0x0000000000000000, 0x0000000000000003, 0x0000000000000000, LoopVectorization.constant, 0x00, 0x02), :LoopVectorization, :getindex, LoopVectorization.OperationStruct(0x0000000000000023, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, LoopVectorization.memload, 0x01, 0x03), :LoopVectorization, :getindex, LoopVectorization.OperationStruct(0x0000000000000023, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, LoopVectorization.memload, 0x02, 0x04), :LoopVectorization, :LOOPCONSTANTINSTRUCTION, LoopVectorization.OperationStruct(0x0000000000000000, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, LoopVectorization.constant, 0x00, 0x05), :LoopVectorization, :getindex, LoopVectorization.OperationStruct(0x0000000000000003, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, LoopVectorization.memload, 0x03, 0x06), :LoopVectorization, :+, LoopVectorization.OperationStruct(0x0000000000000003, 0x0000000000000000, 0x0000000000000000, 0x0000000000000506, LoopVectorization.compute, 0x00, 0x07), :LoopVectorization, :getindex, LoopVectorization.OperationStruct(0x0000000000000031, 0x0000000000000000, 0x0000000000000000, 0x0000000000000007, LoopVectorization.memload, 0x04, 0x08), :LoopVectorization, :getindex, LoopVectorization.OperationStruct(0x0000000000000031, 0x0000000000000000, 0x0000000000000000, 0x0000000000000007, LoopVectorization.memload, 0x05, 0x09), :LoopVectorization, :*, LoopVectorization.OperationStruct(0x0000000000000231, 0x0000000000000000, 0x0000000000000000, 0x0000000000000409, LoopVectorization.compute, 0x00, 0x0a), :LoopVectorization, :-, LoopVectorization.OperationStruct(0x0000000000000123, 0x0000000000000000, 0x0000000000000003, 0x000000000000010a, LoopVectorization.compute, 0x00, 0x0b), :LoopVectorization, :vfmadd, LoopVectorization.OperationStruct(0x0000000000000231, 0x0000000000000003, 0x0000000000000000, 0x000000000003080b, LoopVectorization.compute, 0x00, 0x01), :LoopVectorization, :identity, LoopVectorization.OperationStruct(0x0000000000000012, 0x0000000000000003, 0x0000000000000000, 0x000000000000000c, LoopVectorization.compute, 0x00, 0x01), :LoopVectorization, :*, LoopVectorization.OperationStruct(0x0000000000000231, 0x0000000000000000, 0x0000000000000000, 0x0000000000000408, LoopVectorization.compute, 0x00, 0x0c), :LoopVectorization, :+, LoopVectorization.OperationStruct(0x0000000000000231, 0x0000000000000000, 0x0000000000000003, 0x0000000000000e02, LoopVectorization.compute, 0x00, 0x0d), :LoopVectorization, :vfmadd, LoopVectorization.OperationStruct(0x0000000000000231, 0x0000000000000003, 0x0000000000000000, 0x000000000003090f, LoopVectorization.compute, 0x00, 0x02), :LoopVectorization, :identity, LoopVectorization.OperationStruct(0x0000000000000012, 0x0000000000000003, 0x0000000000000000, 0x0000000000000010, LoopVectorization.compute, 0x00, 0x02), :LoopVectorization, :getindex, LoopVectorization.OperationStruct(0x0000000000000002, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000, LoopVectorization.memload, 0x06, 0x0e), :LoopVectorization, :+, LoopVectorization.OperationStruct(0x0000000000000002, 0x0000000000000000, 0x0000000000000000, 0x0000000000000512, LoopVectorization.compute, 0x00, 0x0f), :LoopVectorization, :setindex!, LoopVectorization.OperationStruct(0x0000000000000021, 0x0000000000000003, 0x0000000000000000, 0x0000000000000d13, LoopVectorization.memstore, 0x07, 0x10), :LoopVectorization, :setindex!, LoopVectorization.OperationStruct(0x0000000000000021, 0x0000000000000003, 0x0000000000000000, 0x0000000000001113, LoopVectorization.memstore, 0x08, 0x11)}
ARF = Tuple{LoopVectorization.ArrayRefStruct{:U_re, Symbol("##vptr##_U_re")}(0x0000000000000101, 0x0000000000000203, 0x0000000000000000), LoopVectorization.ArrayRefStruct{:U_im, Symbol("##vptr##_U_im")}(0x0000000000000101, 0x0000000000000203, 0x0000000000000000), LoopVectorization.ArrayRefStruct{:indices, Symbol("##vptr##_indices")}(0x0000000000000001, 0x0000000000000003, 0x0000000000000000), LoopVectorization.ArrayRefStruct{:st_re, Symbol("##vptr##_st_re")}(0x0000000000000201, 0x0000000000000701, 0x0000000000000000), LoopVectorization.ArrayRefStruct{:st_im, Symbol("##vptr##_st_im")}(0x0000000000000201, 0x0000000000000701, 0x0000000000000000), LoopVectorization.ArrayRefStruct{:indices, Symbol("##vptr##_indices")}(0x0000000000000001, 0x0000000000000002, 0x0000000000000000), LoopVectorization.ArrayRefStruct{:st_re, Symbol("##vptr##_st_re")}(0x0000000000000201, 0x0000000000000f01, 0x0000000000000000), LoopVectorization.ArrayRefStruct{:st_im, Symbol("##vptr##_st_im")}(0x0000000000000201, 0x0000000000000f01, 0x0000000000000000)}
AM = Tuple{0, Tuple{}, Tuple{5}, Tuple{}, Tuple{}, Tuple{(1, LoopVectorization.IntOrFloat), (2, LoopVectorization.IntOrFloat)}, Tuple{}}
LPSYM = Tuple{:b, :i, :j}
LB = Tuple{ArrayInterface.OptionallyStaticUnitRange{ArrayInterface.StaticInt{1}, Int64}, ArrayInterface.OptionallyStaticUnitRange{ArrayInterface.StaticInt{1}, ArrayInterface.StaticInt{8}}, ArrayInterface.OptionallyStaticUnitRange{ArrayInterface.StaticInt{1}, ArrayInterface.StaticInt{8}}}
vargs = (VectorizationBase.StridedPointer{Float64, 2, 1, 0, (1, 2), Tuple{ArrayInterface.StaticInt{8}, ArrayInterface.StaticInt{64}}, Tuple{ArrayInterface.StaticInt{1}, ArrayInterface.StaticInt{1}}}(Ptr{Float64} @0x00007ff2ba5facb0, (ArrayInterface.StaticInt{8}(), ArrayInterface.StaticInt{64}()), (ArrayInterface.StaticInt{1}(), ArrayInterface.StaticInt{1}())), VectorizationBase.StridedPointer{Float64, 2, 1, 0, (1, 2), Tuple{ArrayInterface.StaticInt{8}, ArrayInterface.StaticInt{64}}, Tuple{ArrayInterface.StaticInt{1}, ArrayInterface.StaticInt{1}}}(Ptr{Float64} @0x00007ff2ba5f8450, (ArrayInterface.StaticInt{8}(), ArrayInterface.StaticInt{64}()), (ArrayInterface.StaticInt{1}(), ArrayInterface.StaticInt{1}())), VectorizationBase.StridedPointer{Int64, 1, 1, 0, (1,), Tuple{ArrayInterface.StaticInt{8}}, Tuple{ArrayInterface.StaticInt{1}}}(Ptr{Int64} @0x00007ff2b880eb10, (ArrayInterface.StaticInt{8}(),), (ArrayInterface.StaticInt{1}(),)), VectorizationBase.StridedPointer{Float64, 2, 2, 0, (2, 1), Tuple{Int64, ArrayInterface.StaticInt{8}}, Tuple{ArrayInterface.StaticInt{1}, ArrayInterface.StaticInt{1}}}(Ptr{Float64} @0x000055ecd326d680, (800, ArrayInterface.StaticInt{8}()), (ArrayInterface.StaticInt{1}(), ArrayInterface.StaticInt{1}())), VectorizationBase.StridedPointer{Float64, 2, 2, 0, (2, 1), Tuple{Int64, ArrayInterface.StaticInt{8}}, Tuple{ArrayInterface.StaticInt{1}, ArrayInterface.StaticInt{1}}}(Ptr{Float64} @0x000055ecd246a540, (800, ArrayInterface.StaticInt{8}()), (ArrayInterface.StaticInt{1}(), ArrayInterface.StaticInt{1}())), VectorizationBase.StridedPointer{Int64, 1, 1, 0, (1,), Tuple{ArrayInterface.StaticInt{8}}, Tuple{ArrayInterface.StaticInt{1}}}(Ptr{Int64} @0x00007ff2b880eb10, (ArrayInterface.StaticInt{8}(),), (ArrayInterface.StaticInt{1}(),)), VectorizationBase.StridedPointer{Float64, 2, 2, 0, (2, 1), Tuple{Int64, ArrayInterface.StaticInt{8}}, Tuple{ArrayInterface.StaticInt{1}, ArrayInterface.StaticInt{1}}}(Ptr{Float64} @0x000055ecd326d680, (800, ArrayInterface.StaticInt{8}()), (ArrayInterface.StaticInt{1}(), ArrayInterface.StaticInt{1}())), VectorizationBase.StridedPointer{Float64, 2, 2, 0, (2, 1), Tuple{Int64, ArrayInterface.StaticInt{8}}, Tuple{ArrayInterface.StaticInt{1}, ArrayInterface.StaticInt{1}}}(Ptr{Float64} @0x000055ecd246a540, (800, ArrayInterface.StaticInt{8}()), (ArrayInterface.StaticInt{1}(), ArrayInterface.StaticInt{1}())), 0)

julia> LoopVectorization.choose_order(ls) # Chooses to unroll `b` by 2 and `i` by 4, additionally vectorizes `b`.
([:b, :i, :j], :b, :i, :b, 2, 4)

It chose to unroll b and i by 2  and 4 on my computer, but unrolling i by 4 caused incorrect answers. So I set unroll=(2,8) instead. This is all architecture dependent, meaning saying unroll=(2,8) could mean something different on another computer. You may want to double check on your own. That makes it a truly aweful hack, I just wanted to post something demoing (a) correct results and (b) a speedup.
More importantly, this is a terrible hack in that we're relying on LoopVectorization's current failure to track dependencies between loop iterations. If we remove @avx, we'll get the wrong answer. LLVM won't unroll (i.e., unroll by 1) instead of unrolling by 8, making only 1/8 answers correct. We're counting on this limitation to set a large unroll factor and get behavior matching matmul on blocks.

It currently doesn't like for k in subspace, either. The fix of course is just for _k in eachindex(subspace); k = subspace[_k]. I'll address that in the rewrite to make the transform automatically. The current version already does similar tricks for CartesianIndices{N}, substituting the one loop for N, but the associated code assumes ArrayInterface.static_first(r):ArrayInterface.static_last(r) is approximately idempotent, which obviously isn't the case for vectors, and it makes this assumption in the macro rather than the @generated body, meaning the assumption is made before any awareness of types. So it'd take a bit more work to fix, making it easier to lump in with rewriting the rest of the code anyway.

Finally, a version without those transposed wrappers:
function subspace_mm_t!(
    st_re::AbstractMatrix, st_im::AbstractMatrix,
    indices, U_re::AbstractMatrix{T}, U_im::AbstractMatrix{T}, subspace
) where {T <: Base.HWReal}
    for k in subspace
        @avx unroll=(2,8) for b in axes(st_re, 1)
            for i in axes(U_re, 1)
                y_re= zero(T)
                y_im = zero(T)
                for j in axes(U_re, 2)
                    U_re_i_j = U_re[i,j]
                    U_im_i_j = U_im[i,j]
                    st_re_j_b = st_re[b, k + indices[j]]
                    st_im_j_b = st_im[b, k + indices[j]]
                    y_re += U_re_i_j * st_re_j_b - U_im_i_j * st_im_j_b
                    y_im += U_re_i_j * st_im_j_b + U_im_i_j * st_re_j_b
                end
                st_re[b, k + indices[i]] = y_re
                st_im[b, k + indices[i]] = y_im
            end
        end
    end
    return (st_re, st_im)
end

st_re_t = real.(transpose(st));
st_im_t = imag.(transpose(st));

st_re_t2, st_im_t2 = subspace_mm_t!((copy(st_re_t)), (copy(st_im_t)), indices, MU_re, MU_im,  subspace);
st_re_t2 ≈ real.(st2)'
st_im_t2 ≈ imag.(st2)'

@benchmark subspace_mm_t!($(copy(st_re_t)), $(copy(st_im_t)), $indices, $MU_re, $MU_im,  $subspace)

Finally, I get
julia> st2 = subspace_smm!((copy(st)), indices, SU, subspace);

julia> st_re2, st_im2 = subspace_mm!((deepcopy(st_re)), (deepcopy(st_im)), indices, MU_re, MU_im,  subspace);

julia> st_re2 ≈ real.(st2)
true

julia> st_im2 ≈ imag.(st2)
true

julia> sindices = SVector(indices...);

julia> @benchmark subspace_smm!($(copy(st)), $sindices, $SU, $subspace)
BenchmarkTools.Trial:
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     110.086 μs (0.00% GC)
  median time:      110.462 μs (0.00% GC)
  mean time:        110.517 μs (0.00% GC)
  maximum time:     252.352 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark subspace_mm!($(deepcopy(st_re)), $(deepcopy(st_im)), $indices, $MU_re, $MU_im,  $subspace)
BenchmarkTools.Trial:
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     32.655 μs (0.00% GC)
  median time:      33.060 μs (0.00% GC)
  mean time:        33.108 μs (0.00% GC)
  maximum time:     98.802 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> st_re_t2, st_im_t2 = subspace_mm_t!((copy(st_re_t)), (copy(st_im_t)), indices, MU_re, MU_im,  subspace);

julia> st_re_t2 ≈ real.(st2)'
true

julia> st_im_t2 ≈ imag.(st2)'
true

julia> @benchmark subspace_mm_t!($(copy(st_re_t)), $(copy(st_im_t)), $indices, $MU_re, $MU_im,  $subspace)
BenchmarkTools.Trial:
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     31.613 μs (0.00% GC)
  median time:      31.952 μs (0.00% GC)
  mean time:        31.992 μs (0.00% GC)
  maximum time:     87.974 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

Another solution
using LoopVectorization, PaddedMatrices
function AmulB!(Cre, Cim, Are, Aim, Bre, Bim)
    @avx for n in axes(Cre,2), m in axes(Cre,1)
        Cre_mn = zero(eltype(Cre))
        Cim_mn = zero(eltype(Cim))
        for k in axes(Bre,1)
            Cre_mn += Are[m,k] * Bre[k,n] - Aim[m,k] * Bim[k,n]
            Cim_mn += Are[m,k] * Bim[k,n] + Aim[m,k] * Bre[k,n]
        end
        Cre[m,n] = Cre_mn
        Cim[m,n] = Cim_mn
    end
end

function subspace_smm_mul!(st_re::AbstractMatrix{T}, st_im::AbstractMatrix, indices, U_re::AbstractMatrix, U_im, subspace) where {T}
    A_re = StrideArray{T}(undef, (PaddedMatrices. size(st_re, StaticInt(1)), PaddedMatrices.static_length(indices)))
    A_im = similar(A_re)
    C_re = similar(A_re)
    C_im = similar(A_im)
    for k in subspace
        idx = k .+ indices
        @avx for i in eachindex(idx), j in axes(A_re,1)
            A_re[j,i] = st_re[j,idx[i]]
            A_im[j,i] = st_im[j,idx[i]]
        end
        @gc_preserve AmulB!(C_re, C_im, A_re, A_im, U_re', U_im')
        @avx for i in eachindex(idx), j in axes(A_re,1)
            st_re[j,idx[i]] = C_re[j,i]
            st_im[j,idx[i]] = C_im[j,i]
        end
    end
    return st_re, st_im
end

# Need a more convenient API for this
function stride_array(A, sz = PaddedMatrices.size(A))
    StrideArray(PtrArray(stridedpointer(A), sz, PaddedMatrices.ArrayInterface.dense_dims(A)), A)
end

# Make the first dimension static
s_st_re = stride_array(st_re_t, (StaticInt(size(st_re_t,1)),size(st_re_t,2)));
s_st_im = stride_array(st_im_t, (StaticInt(size(st_im_t,1)),size(st_im_t,2)));

s_indices = stride_array(indices, (StaticInt(length(indices)),));

s_st_re2, s_st_im2 = subspace_smm_mul!(copy(s_st_re), copy(s_st_im), s_indices, MU_re, MU_im, subspace)

s_st_re2 ≈ real.(st2)'
s_st_im2 ≈ imag.(st2)'

@benchmark subspace_smm_mul!($(copy(s_st_re)), $(copy(s_st_im)), $s_indices, $MU_re, $MU_im, $subspace)

This yields:
julia> s_st_re2 ≈ real.(st2)'
true

julia> s_st_im2 ≈ imag.(st2)'
true

julia> @benchmark subspace_smm_mul!($(copy(s_st_re)), $(copy(s_st_im)), $s_indices, $MU_re, $MU_im, $subspace)
BenchmarkTools.Trial:
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     43.063 μs (0.00% GC)
  median time:      43.460 μs (0.00% GC)
  mean time:        43.526 μs (0.00% GC)
  maximum time:     97.375 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

This has the advantage that it doesn't rely on undefined behavior and should work when you change array sizes. It has the disadvantage that, as is, it does a lot of copying of memory back and fourth.
Once I (or someone else) implements:
julia> stridedpointer(view(rand(16,16), :, [1,2,5,7]))
ERROR: "Memory access for SubArray{Float64, 2, Matrix{Float64}, Tuple{Base.Slice{Base.OneTo{Int64}}, Vector{Int64}}, false} not implemented yet."
Stacktrace:
 [1] memory_reference
   @ ~/.julia/dev/VectorizationBase/src/strided_pointers/stridedpointers.jl:45 [inlined]
 [2] memory_reference
   @ ~/.julia/dev/VectorizationBase/src/strided_pointers/stridedpointers.jl:35 [inlined]
 [3] stridedpointer(A::SubArray{Float64, 2, Matrix{Float64}, Tuple{Base.Slice{Base.OneTo{Int64}}, Vector{Int64}}, false})
   @ VectorizationBase ~/.julia/dev/VectorizationBase/src/strided_pointers/stridedpointers.jl:72
 [4] top-level scope
   @ REPL[68]:1

We could get rid of Cre/Cim, and just pass views to st_re/st_im.

wow thanks for such a detailed reply! I didn't expect there's still a 3x speedup comparing to SA version, this is very impressive! But I'm wondering if @avx accepts reinterpret since I won't be able to change the memory layout of st and because this operation will be performing at st size between (1 << 8, 1000) ~ (1 << 30, 1000), using real and imag to copy the memory could be very expensive at larger scale. (or maybe it's possible for LoopVectorization to specialize ComplexF64 and ComplexF32 using reinterpret?)

The new reinterpret(reshape, ...) is great for this:
julia> A = rand(ComplexF64, 3, 4)
3×4 Matrix{ComplexF64}:
 0.255597+0.833728im  0.538941+0.632544im  0.689762+0.322061im  0.0550905+0.186901im
 0.392467+0.609713im  0.408867+0.111692im  0.574269+0.602653im   0.760552+0.385366im
 0.221208+0.544642im  0.928497+0.13649im   0.782709+0.872457im   0.460958+0.809076im

julia> reinterpret(reshape, Float64, A)
2×3×4 reinterpret(reshape, Float64, ::Matrix{ComplexF64}) with eltype Float64:
[:, :, 1] =
 0.255597  0.392467  0.221208
 0.833728  0.609713  0.544642

[:, :, 2] =
 0.538941  0.408867  0.928497
 0.632544  0.111692  0.13649

[:, :, 3] =
 0.689762  0.574269  0.782709
 0.322061  0.602653  0.872457

[:, :, 4] =
 0.0550905  0.760552  0.460958
 0.186901   0.385366  0.809076

It should work:
julia> stridedpointer(reinterpret(reshape, Float64, A))
VectorizationBase.StridedPointer{Float64, 3, 1, 0, (1, 2, 3), Tuple{StaticInt{8}, StaticInt{16}, Int64}, Tuple{StaticInt{1}, StaticInt{1}, StaticInt{1}}}(Ptr{Float64} @0x00007f7197724050, (StaticInt{8}(),
StaticInt{16}(), 48), (StaticInt{1}(), StaticInt{1}(), StaticInt{1}()))

julia> using LoopVectorization

julia> LoopVectorization.check_args(reinterpret(reshape, Float64, A))
true

Here is an implementation using the same inputs as the old version:
using StaticArrays, BenchmarkTools

n = 3
st = rand(ComplexF64, 1 << 8, 100);
y = similar(st, (1 << n, 100));
U = rand(ComplexF64, 1 << n, 1 << n);
SU = @SMatrix rand(ComplexF64, 1 << n, 1 << n);
indices = [1, 2, 5, 6, 9, 10, 13, 14];
subspace = [0, 2, 16, 18, 32, 34, 48, 50, 64, 66, 80, 82, 96, 98, 112, 114, 128, 130, 144, 146, 160, 162, 176, 178, 192, 194, 208, 210, 224, 226, 240, 242];

function subspace_smm!(st::AbstractMatrix, indices, U::AbstractMatrix, subspace)
    @inbounds @views for k in subspace
        idx = k .+ indices
        for b in 1:size(st, 2)
            st[idx, b] = U * st[idx, b]
        end
    end
    return st
end

using PaddedMatrices, LoopVectorization

function subspace_smm_avx!(st::AbstractMatrix{Complex{T}}, indices::StrideArray, U::AbstractMatrix, subspace) where {T}

    C_re = StrideArray{T}(undef, (PaddedMatrices.static_length(indices), StaticInt{8}()))
    C_im = StrideArray{T}(undef, (PaddedMatrices.static_length(indices), StaticInt{8}()))
    U_re = StrideArray{T}(undef, (PaddedMatrices.size(U, StaticInt{1}()), PaddedMatrices.size(U, StaticInt{2}())))
    U_im = StrideArray{T}(undef, (PaddedMatrices.size(U, StaticInt{1}()), PaddedMatrices.size(U, StaticInt{2}())))
    Ur = reinterpret(reshape, T, U)
    @inbounds @simd ivdep for i ∈ eachindex(U_re)
        U_re[i] = Ur[1,i]
        U_im[i] = Ur[2,i]
    end
    str = reinterpret(reshape, T, st)

    Bmax = size(st,2)
    for k in subspace
        # idx = k .+ indices
        # _k = k - 1
        for _b ∈ 0:(Bmax-1) >>> 3
            b =    _b << 3;
            bmax = b + 8
            if bmax ≤ Bmax # full static block
                @avx for n ∈ 1:8, m ∈ axes(U, 1)
                    C_re_m_n = zero(T)
                    C_im_m_n = zero(T)
                    for i ∈ axes(U, 2)
                        str_i = k + indices[i]
                        C_re_m_n += U_re[m,i] * str[1,str_i,n+b] - U_im[m,i] * str[2,str_i,n+b]
                        C_im_m_n += U_re[m,i] * str[2,str_i,n+b] + U_im[m,i] * str[1,str_i,n+b]
                    end
                    C_re[m,n] = C_re_m_n
                    C_im[m,n] = C_im_m_n
                end
                @avx for n ∈ 1:8, m ∈ axes(U, 1)
                    str_m = k + indices[m]
                    str[1,str_m,n+b] = C_re[m,n]
                    str[2,str_m,n+b] = C_im[m,n]
                end
                # AmulB!(C_re, C_im, U_re, U_im,
            else # dynamic block
                Nmax = 8 + Bmax - bmax
                @avx for n ∈ 1:Nmax, m ∈ axes(U, 1)
                    C_re_m_n = zero(T)
                    C_im_m_n = zero(T)
                    for i ∈ axes(U, 2)
                        str_i = k + indices[i]
                        C_re_m_n += U_re[m,i] * str[1,str_i,n+b] - U_im[m,i] * str[2,str_i,n+b]
                        C_im_m_n += U_re[m,i] * str[2,str_i,n+b] + U_im[m,i] * str[1,str_i,n+b]
                    end
                    C_re[m,n] = C_re_m_n
                    C_im[m,n] = C_im_m_n
                end
                @avx for n ∈ 1:Nmax, m ∈ axes(U, 1)
                    str_m = k + indices[m]
                    str[1,str_m,n+b] = C_re[m,n]
                    str[2,str_m,n+b] = C_im[m,n]
                end
            end
        end
    end
    return st
end

static_indices = SVector(indices...);
stride_indices = StrideArray(MVector(static_indices));

st2 = subspace_smm!((copy(st)), static_indices, SU, subspace);
st3 = subspace_smm_avx!((copy(st)), stride_indices, SU, subspace);
st2 ≈ st3

@benchmark subspace_smm!($(copy(st)), $static_indices, $SU, $subspace)
@benchmark subspace_smm_avx!($(copy(st)), $stride_indices, $SU, $subspace)

Results (on a different computer than last time):
julia> st2 = subspace_smm!((copy(st)), static_indices, SU, subspace);

julia> st3 = subspace_smm_avx!((copy(st)), stride_indices, SU, subspace);

julia> st2 ≈ st3
true

julia> @benchmark subspace_smm!($(copy(st)), $static_indices, $SU, $subspace)
BenchmarkTools.Trial:
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     120.998 μs (0.00% GC)
  median time:      124.350 μs (0.00% GC)
  mean time:        127.713 μs (0.00% GC)
  maximum time:     207.639 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark subspace_smm_avx!($(copy(st)), $stride_indices, $SU, $subspace)
BenchmarkTools.Trial:
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     37.980 μs (0.00% GC)
  median time:      38.166 μs (0.00% GC)
  mean time:        39.356 μs (0.00% GC)
  maximum time:     78.841 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

From a performance perspective, our goal is to  make the most out of our vector units. That now means, we want to SIMD U. We pay the price of going from array of structs (U) to separate arrays (U_re, U_im) once, up front.
While loading vectors from U, we're only loading scalars from str, so we can load directly / no need to change memory layout.
We do need a separate array to copy memory into however, because neither A or B is allowed to alias C in C = A * B.
So we create a destination C_{re/im} with a layout that matches U_{re/im} for efficient writing, and then copy it over to st when done.
Also, we iterate over blocks of b rather than 1 at a time. That's because loads from U are independent of b, so by unrolling it we get more reuse. AVX512 would probably benefit frmo even larger block sizes, but AVX2 probably won't really benefit from more than 2 (based on register use/available in the inner loops).
LoopVectorization will subdivide those blocks appropriately, so making them larger should be safe.
I wanted a statically sized upper limit, so that we could stack allocate all our temporaries.

Wow this is very impressive. I further benchmarked your implementation with a manual loop version, and a fully expanded 4x4 and 8x8 version, @avx is slower in the 2x2 and 4x4 case (which I guess requires some tune on the block size, but these two cases are fairly easy to implement directly by unrolling the loop), but faster when U is larger than 8x8. I have to change the implementation a bit since I need to generate the subspace indices on the fly (the subspace and comspace function), I'll post a repo link later for the utils of creating subspace object so one can reproduce the benchmark I list here.
Implementation
function subspace_mul!(st::AbstractMatrix, comspace, U::AbstractMatrix{T}, subspace) where T
    y = similar(st, (size(U, 1), ))
    indices = [b + 1 for b in comspace]::Vector{Int}
    idx = similar(indices)
    @inbounds for k in subspace, b in 1:size(st, 2)
        for i in 1:size(U, 1)
            idx[i] = k + indices[i]
        end

        for i in 1:size(U, 1)
            y[i] = zero(T)
            for j in 1:size(U, 2)
                y[i] += U[i, j] * st[idx[j], b]
            end
        end

        for i in 1:size(U, 1)
            st[idx[i], b] = y[i]
        end
    end
    return st
end

function subspace_mul_avx!(st::AbstractMatrix, comspace, U::AbstractMatrix{Complex{T}}, subspace) where T
    indices = StrideArray{Int}(undef, (length(comspace), ))
    @simd ivdep for i in 1:length(comspace)
        indices[i] = comspace[i] + 1
    end

    C_re = StrideArray{T}(undef, (PaddedMatrices.static_length(indices), StaticInt{32}()))
    C_im = StrideArray{T}(undef, (PaddedMatrices.static_length(indices), StaticInt{32}()))
    U_re = StrideArray{T}(undef, (PaddedMatrices.size(U, StaticInt{1}()), PaddedMatrices.size(U, StaticInt{2}())))
    U_im = StrideArray{T}(undef, (PaddedMatrices.size(U, StaticInt{1}()), PaddedMatrices.size(U, StaticInt{2}())))
    Ur = reinterpret(reshape, T, U)

    @inbounds @simd ivdep for i ∈ eachindex(U_re)
        U_re[i] = Ur[1,i]
        U_im[i] = Ur[2,i]
    end
    str = reinterpret(reshape, T, st)
    Bmax = size(st,2)
    for k in subspace
        # idx = k .+ indices
        # _k = k - 1
        for _b ∈ 0:(Bmax-1) >>> 5
            b =    _b << 5;
            bmax = b + 32
            if bmax ≤ Bmax # full static block
                @avx for n ∈ 1:32, m ∈ axes(U, 1)
                    C_re_m_n = zero(T)
                    C_im_m_n = zero(T)
                    for i ∈ axes(U, 2)
                        str_i = k + indices[i]
                        C_re_m_n += U_re[m,i] * str[1,str_i,n+b] - U_im[m,i] * str[2,str_i,n+b]
                        C_im_m_n += U_re[m,i] * str[2,str_i,n+b] + U_im[m,i] * str[1,str_i,n+b]
                    end
                    C_re[m,n] = C_re_m_n
                    C_im[m,n] = C_im_m_n
                end
                @avx for n ∈ 1:32, m ∈ axes(U, 1)
                    str_m = k + indices[m]
                    str[1,str_m,n+b] = C_re[m,n]
                    str[2,str_m,n+b] = C_im[m,n]
                end
                # AmulB!(C_re, C_im, U_re, U_im,
            else # dynamic block
                Nmax = 32 + Bmax - bmax
                @avx for n ∈ 1:Nmax, m ∈ axes(U, 1)
                    C_re_m_n = zero(T)
                    C_im_m_n = zero(T)
                    for i ∈ axes(U, 2)
                        str_i = k + indices[i]
                        C_re_m_n += U_re[m,i] * str[1,str_i,n+b] - U_im[m,i] * str[2,str_i,n+b]
                        C_im_m_n += U_re[m,i] * str[2,str_i,n+b] + U_im[m,i] * str[1,str_i,n+b]
                    end
                    C_re[m,n] = C_re_m_n
                    C_im[m,n] = C_im_m_n
                end
                @avx for n ∈ 1:Nmax, m ∈ axes(U, 1)
                    str_m = k + indices[m]
                    str[1,str_m,n+b] = C_re[m,n]
                    str[2,str_m,n+b] = C_im[m,n]
                end
            end
        end
    end
    return st
end

function subspace_mul4x4!(st::AbstractMatrix{T}, comspace, U::AbstractMatrix, subspace, offset=0) where T
    Base.Cartesian.@nextract 4 indices i -> comspace[i] + 1

    Base.Cartesian.@nextract 4 U i->begin
        Base.Cartesian.@nextract 4 U_i j->U[i, j]
    end

    @inbounds for k in subspace
        Base.Cartesian.@nextract 4 idx i-> k + indices_i + offset

        for b in 1:size(st, 2)
            Base.Cartesian.@nexprs 4 i -> begin
                y_i = zero(T)
                Base.Cartesian.@nexprs 4 j -> begin
                    y_i += U_i_j * st[idx_j, b]
                end
            end

            Base.Cartesian.@nexprs 4 i -> begin
                st[idx_i, b] = y_i
            end
        end
    end
    return st
end

function subspace_mul8x8!(st::AbstractMatrix{T}, comspace, U::AbstractMatrix, subspace, offset=0) where T
    Base.Cartesian.@nextract 8 indices i -> comspace[i] + 1

    Base.Cartesian.@nextract 8 U i->begin
        Base.Cartesian.@nextract 8 U_i j->U[i, j]
    end

    @inbounds for k in subspace
        Base.Cartesian.@nextract 8 idx i-> k + indices_i + offset

        for b in 1:size(st, 2)
            Base.Cartesian.@nexprs 8 i -> begin
                y_i = zero(T)
                Base.Cartesian.@nexprs 8 j -> begin
                    y_i += U_i_j * st[idx_j, b]
                end
            end

            Base.Cartesian.@nexprs 8 i -> begin
                st[idx_i, b] = y_i
            end
        end
    end
    return st
end

I set the block size to 32 here, since I find it works better than 8 on my machine. But I'm not sure how should one tune this parameter.
Benchmark
4x4 benchmark
n = 8
locs = Locations((1, 3))
st = rand(ComplexF64, 1 << n, 100)
U = rand(ComplexF64, 1 << 2, 1 << 2)
subspace = bsubspace(n, locs)
comspace = bcomspace(n, locs)

julia> @benchmark subspace_mul4x4!($(copy(st)), $comspace, $U, $subspace)
BenchmarkTools.Trial:
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     44.049 μs (0.00% GC)
  median time:      45.199 μs (0.00% GC)
  mean time:        45.260 μs (0.00% GC)
  maximum time:     98.788 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark subspace_mul!($(copy(st)), $comspace, $U, $subspace)
BenchmarkTools.Trial:
  memory estimate:  368 bytes
  allocs estimate:  3
  --------------
  minimum time:     145.357 μs (0.00% GC)
  median time:      169.142 μs (0.00% GC)
  mean time:        172.254 μs (0.00% GC)
  maximum time:     218.237 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark subspace_mul_avx!($(copy(st)), $comspace, $U, $subspace)
BenchmarkTools.Trial:
  memory estimate:  2.80 KiB
  allocs estimate:  5
  --------------
  minimum time:     91.348 μs (0.00% GC)
  median time:      93.869 μs (0.00% GC)
  mean time:        94.103 μs (0.00% GC)
  maximum time:     107.998 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

8x8 benchmark
n = 8
locs = Locations((1, 3, 4))
st = rand(ComplexF64, 1 << n, 100)
U = rand(ComplexF64, 1 << 3, 1 << 3)
subspace = bsubspace(n, locs)
comspace = bcomspace(n, locs)

julia> @benchmark subspace_mul8x8!($(copy(st)), $comspace, $U, $subspace)
BenchmarkTools.Trial:
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     100.238 μs (0.00% GC)
  median time:      102.818 μs (0.00% GC)
  mean time:        102.973 μs (0.00% GC)
  maximum time:     129.718 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark subspace_mul!($(copy(st)), $comspace, $U, $subspace)
BenchmarkTools.Trial:
  memory estimate:  496 bytes
  allocs estimate:  3
  --------------
  minimum time:     203.286 μs (0.00% GC)
  median time:      234.566 μs (0.00% GC)
  mean time:        226.253 μs (0.00% GC)
  maximum time:     274.735 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark subspace_mul_avx!($(copy(st)), $comspace, $U, $subspace)
BenchmarkTools.Trial:
  memory estimate:  5.61 KiB
  allocs estimate:  5
  --------------
  minimum time:     72.709 μs (0.00% GC)
  median time:      74.358 μs (0.00% GC)
  mean time:        74.602 μs (0.00% GC)
  maximum time:     213.575 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

16x16 benchmark
n = 8
locs = Locations((1, 3, 4, 5))
st = rand(ComplexF64, 1 << n, 100)
U = rand(ComplexF64, 1 << 4, 1 << 4)
subspace = bsubspace(n, locs)
comspace = bcomspace(n, locs)

julia> @benchmark subspace_mul!($(copy(st)), $comspace, $U, $subspace)
BenchmarkTools.Trial:
  memory estimate:  752 bytes
  allocs estimate:  3
  --------------
  minimum time:     421.922 μs (0.00% GC)
  median time:      438.516 μs (0.00% GC)
  mean time:        448.164 μs (0.00% GC)
  maximum time:     703.526 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark subspace_mul_avx!($(copy(st)), $comspace, $U, $subspace)
BenchmarkTools.Trial:
  memory estimate:  12.70 KiB
  allocs estimate:  5
  --------------
  minimum time:     101.148 μs (0.00% GC)
  median time:      104.228 μs (0.00% GC)
  mean time:        104.850 μs (0.43% GC)
  maximum time:     2.390 ms (94.51% GC)
  --------------
  samples:          10000
  evals/sample:     1

But I still have a few questions about the above implementation:

I tried to use transpose(rand(100, 1<<8))  instead of rand(1<<8, 100), based on previous discussion, however, stridedpointer complains

ERROR: ArgumentError: Parent must be strided.
Stacktrace:
  [1] |>(x::ArgumentError, f::typeof(throw))
    @ Base ./operators.jl:839
  [2] strides(a::Base.ReinterpretArray{Float64, 3, ComplexF64, LinearAlgebra.Transpose{ComplexF64, Matrix{ComplexF64}}, true})
    @ Base ./reinterpretarray.jl:157
  [3] strides
    @ ~/.julia/packages/ArrayInterface/q5Rwc/src/stridelayout.jl:287 [inlined]
  [4] bytestrides
    @ ~/.julia/packages/VectorizationBase/oXigE/src/strided_pointers/stridedpointers.jl:21 [inlined]
  [5] stridedpointer
    @ ~/.julia/packages/VectorizationBase/oXigE/src/strided_pointers/stridedpointers.jl:72 [inlined]

is it beneficial to be able to use the more contiguous layout in the last implementation? if it is, how can I use it with StrideArray?

In my benchmark, it seems Julia fails to allocate the tempries on stack, I tried to remove the subspace and comspace and use a constant indices like the previous benchmarks, but that didn't help. I'm running this on Julia-1.6, could this because of the updates in Julia-1.6? @chriselrod which julia version were you using?

Wow this is very impressive. I further benchmarked your implementation with a manual loop version, and a fully expanded 4x4 and 8x8 version, @avx is slower in the 2x2 and 4x4 case (which I guess requires some tune on the block size, but these two cases are fairly easy to implement directly by unrolling the loop), but faster when U is larger than 8x8. I have to change the implementation a bit since I need to generate the subspace indices on the fly (the subspace and comspace function), I'll post a repo link later for the utils of creating subspace object so one can reproduce the benchmark I list here.
Implementation
function subspace_mul!(st::AbstractMatrix, comspace, U::AbstractMatrix{T}, subspace) where T
    y = similar(st, (size(U, 1), ))
    indices = [b + 1 for b in comspace]::Vector{Int}
    idx = similar(indices)
    @inbounds for k in subspace, b in 1:size(st, 2)
        for i in 1:size(U, 1)
            idx[i] = k + indices[i]
        end

        for i in 1:size(U, 1)
            y[i] = zero(T)
            for j in 1:size(U, 2)
                y[i] += U[i, j] * st[idx[j], b]
            end
        end

        for i in 1:size(U, 1)
            st[idx[i], b] = y[i]
        end
    end
    return st
end

function subspace_mul_avx!(st::AbstractMatrix, comspace, U::AbstractMatrix{Complex{T}}, subspace) where T
    indices = StrideArray{Int}(undef, (length(comspace), ))
    @simd ivdep for i in 1:length(comspace)
        indices[i] = comspace[i] + 1
    end

    C_re = StrideArray{T}(undef, (PaddedMatrices.static_length(indices), StaticInt{32}()))
    C_im = StrideArray{T}(undef, (PaddedMatrices.static_length(indices), StaticInt{32}()))
    U_re = StrideArray{T}(undef, (PaddedMatrices.size(U, StaticInt{1}()), PaddedMatrices.size(U, StaticInt{2}())))
    U_im = StrideArray{T}(undef, (PaddedMatrices.size(U, StaticInt{1}()), PaddedMatrices.size(U, StaticInt{2}())))
    Ur = reinterpret(reshape, T, U)

    @inbounds @simd ivdep for i ∈ eachindex(U_re)
        U_re[i] = Ur[1,i]
        U_im[i] = Ur[2,i]
    end
    str = reinterpret(reshape, T, st)
    Bmax = size(st,2)
    for k in subspace
        # idx = k .+ indices
        # _k = k - 1
        for _b ∈ 0:(Bmax-1) >>> 5
            b =    _b << 5;
            bmax = b + 32
            if bmax ≤ Bmax # full static block
                @avx for n ∈ 1:32, m ∈ axes(U, 1)
                    C_re_m_n = zero(T)
                    C_im_m_n = zero(T)
                    for i ∈ axes(U, 2)
                        str_i = k + indices[i]
                        C_re_m_n += U_re[m,i] * str[1,str_i,n+b] - U_im[m,i] * str[2,str_i,n+b]
                        C_im_m_n += U_re[m,i] * str[2,str_i,n+b] + U_im[m,i] * str[1,str_i,n+b]
                    end
                    C_re[m,n] = C_re_m_n
                    C_im[m,n] = C_im_m_n
                end
                @avx for n ∈ 1:32, m ∈ axes(U, 1)
                    str_m = k + indices[m]
                    str[1,str_m,n+b] = C_re[m,n]
                    str[2,str_m,n+b] = C_im[m,n]
                end
                # AmulB!(C_re, C_im, U_re, U_im,
            else # dynamic block
                Nmax = 32 + Bmax - bmax
                @avx for n ∈ 1:Nmax, m ∈ axes(U, 1)
                    C_re_m_n = zero(T)
                    C_im_m_n = zero(T)
                    for i ∈ axes(U, 2)
                        str_i = k + indices[i]
                        C_re_m_n += U_re[m,i] * str[1,str_i,n+b] - U_im[m,i] * str[2,str_i,n+b]
                        C_im_m_n += U_re[m,i] * str[2,str_i,n+b] + U_im[m,i] * str[1,str_i,n+b]
                    end
                    C_re[m,n] = C_re_m_n
                    C_im[m,n] = C_im_m_n
                end
                @avx for n ∈ 1:Nmax, m ∈ axes(U, 1)
                    str_m = k + indices[m]
                    str[1,str_m,n+b] = C_re[m,n]
                    str[2,str_m,n+b] = C_im[m,n]
                end
            end
        end
    end
    return st
end

function subspace_mul4x4!(st::AbstractMatrix{T}, comspace, U::AbstractMatrix, subspace, offset=0) where T
    Base.Cartesian.@nextract 4 indices i -> comspace[i] + 1

    Base.Cartesian.@nextract 4 U i->begin
        Base.Cartesian.@nextract 4 U_i j->U[i, j]
    end

    @inbounds for k in subspace
        Base.Cartesian.@nextract 4 idx i-> k + indices_i + offset

        for b in 1:size(st, 2)
            Base.Cartesian.@nexprs 4 i -> begin
                y_i = zero(T)
                Base.Cartesian.@nexprs 4 j -> begin
                    y_i += U_i_j * st[idx_j, b]
                end
            end

            Base.Cartesian.@nexprs 4 i -> begin
                st[idx_i, b] = y_i
            end
        end
    end
    return st
end

function subspace_mul8x8!(st::AbstractMatrix{T}, comspace, U::AbstractMatrix, subspace, offset=0) where T
    Base.Cartesian.@nextract 8 indices i -> comspace[i] + 1

    Base.Cartesian.@nextract 8 U i->begin
        Base.Cartesian.@nextract 8 U_i j->U[i, j]
    end

    @inbounds for k in subspace
        Base.Cartesian.@nextract 8 idx i-> k + indices_i + offset

        for b in 1:size(st, 2)
            Base.Cartesian.@nexprs 8 i -> begin
                y_i = zero(T)
                Base.Cartesian.@nexprs 8 j -> begin
                    y_i += U_i_j * st[idx_j, b]
                end
            end

            Base.Cartesian.@nexprs 8 i -> begin
                st[idx_i, b] = y_i
            end
        end
    end
    return st
end

I set the block size to 32 here, since I find it works better than 8 on my machine. But I'm not sure how should one tune this parameter.
Benchmark
4x4 benchmark
n = 8
locs = Locations((1, 3))
st = rand(ComplexF64, 1 << n, 100)
U = rand(ComplexF64, 1 << 2, 1 << 2)
subspace = bsubspace(n, locs)
comspace = bcomspace(n, locs)

julia> @benchmark subspace_mul4x4!($(copy(st)), $comspace, $U, $subspace)
BenchmarkTools.Trial:
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     44.049 μs (0.00% GC)
  median time:      45.199 μs (0.00% GC)
  mean time:        45.260 μs (0.00% GC)
  maximum time:     98.788 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark subspace_mul!($(copy(st)), $comspace, $U, $subspace)
BenchmarkTools.Trial:
  memory estimate:  368 bytes
  allocs estimate:  3
  --------------
  minimum time:     145.357 μs (0.00% GC)
  median time:      169.142 μs (0.00% GC)
  mean time:        172.254 μs (0.00% GC)
  maximum time:     218.237 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark subspace_mul_avx!($(copy(st)), $comspace, $U, $subspace)
BenchmarkTools.Trial:
  memory estimate:  2.80 KiB
  allocs estimate:  5
  --------------
  minimum time:     91.348 μs (0.00% GC)
  median time:      93.869 μs (0.00% GC)
  mean time:        94.103 μs (0.00% GC)
  maximum time:     107.998 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

8x8 benchmark
n = 8
locs = Locations((1, 3, 4))
st = rand(ComplexF64, 1 << n, 100)
U = rand(ComplexF64, 1 << 3, 1 << 3)
subspace = bsubspace(n, locs)
comspace = bcomspace(n, locs)

julia> @benchmark subspace_mul8x8!($(copy(st)), $comspace, $U, $subspace)
BenchmarkTools.Trial:
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     100.238 μs (0.00% GC)
  median time:      102.818 μs (0.00% GC)
  mean time:        102.973 μs (0.00% GC)
  maximum time:     129.718 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark subspace_mul!($(copy(st)), $comspace, $U, $subspace)
BenchmarkTools.Trial:
  memory estimate:  496 bytes
  allocs estimate:  3
  --------------
  minimum time:     203.286 μs (0.00% GC)
  median time:      234.566 μs (0.00% GC)
  mean time:        226.253 μs (0.00% GC)
  maximum time:     274.735 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark subspace_mul_avx!($(copy(st)), $comspace, $U, $subspace)
BenchmarkTools.Trial:
  memory estimate:  5.61 KiB
  allocs estimate:  5
  --------------
  minimum time:     72.709 μs (0.00% GC)
  median time:      74.358 μs (0.00% GC)
  mean time:        74.602 μs (0.00% GC)
  maximum time:     213.575 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

16x16 benchmark
n = 8
locs = Locations((1, 3, 4, 5))
st = rand(ComplexF64, 1 << n, 100)
U = rand(ComplexF64, 1 << 4, 1 << 4)
subspace = bsubspace(n, locs)
comspace = bcomspace(n, locs)

julia> @benchmark subspace_mul!($(copy(st)), $comspace, $U, $subspace)
BenchmarkTools.Trial:
  memory estimate:  752 bytes
  allocs estimate:  3
  --------------
  minimum time:     421.922 μs (0.00% GC)
  median time:      438.516 μs (0.00% GC)
  mean time:        448.164 μs (0.00% GC)
  maximum time:     703.526 μs (0.00% GC)
  --------------
  samples:          10000
  evals/sample:     1

julia> @benchmark subspace_mul_avx!($(copy(st)), $comspace, $U, $subspace)
BenchmarkTools.Trial:
  memory estimate:  12.70 KiB
  allocs estimate:  5
  --------------
  minimum time:     101.148 μs (0.00% GC)
  median time:      104.228 μs (0.00% GC)
  mean time:        104.850 μs (0.43% GC)
  maximum time:     2.390 ms (94.51% GC)
  --------------
  samples:          10000
  evals/sample:     1

But I still have a few questions about the above implementation:

I tried to use transpose(rand(100, 1<<8))  instead of rand(1<<8, 100), based on previous discussion, however, stridedpointer complains

ERROR: ArgumentError: Parent must be strided.
Stacktrace:
  [1] |>(x::ArgumentError, f::typeof(throw))
    @ Base ./operators.jl:839
  [2] strides(a::Base.ReinterpretArray{Float64, 3, ComplexF64, LinearAlgebra.Transpose{ComplexF64, Matrix{ComplexF64}}, true})
    @ Base ./reinterpretarray.jl:157
  [3] strides
    @ ~/.julia/packages/ArrayInterface/q5Rwc/src/stridelayout.jl:287 [inlined]
  [4] bytestrides
    @ ~/.julia/packages/VectorizationBase/oXigE/src/strided_pointers/stridedpointers.jl:21 [inlined]
  [5] stridedpointer
    @ ~/.julia/packages/VectorizationBase/oXigE/src/strided_pointers/stridedpointers.jl:72 [inlined]

is it beneficial to be able to use the more contiguous layout in the last implementation? if it is, how can I use it with StrideArray?

In my benchmark, it seems Julia fails to allocate the tempries on stack, I tried to remove the subspace and comspace and use a constant indices like the previous benchmarks, but that didn't help. I'm running this on Julia-1.6, could this because of the updates in Julia-1.6? @chriselrod which julia version were you using?

In my benchmark, it seems Julia fails to allocate the tempries on stack, I tried to remove the subspace and comspace and use a constant indices like the previous benchmarks, but that didn't help. I'm running this on Julia-1.6, could this because of the updates in Julia-1.6? @chriselrod which julia version were you using?

I was using Julia 1.6. For the arrays to be stack allocated (in Julia -- Fortran can stack allocate dynamically sized arrays), the size has to be known at compile time. So all the dimensions of these temporaries:
    indices = StrideArray{Int}(undef, (length(comspace), ))
    @simd ivdep for i in 1:length(comspace)
        indices[i] = comspace[i] + 1
    end

    C_re = StrideArray{T}(undef, (PaddedMatrices.static_length(indices), StaticInt{32}()))
    C_im = StrideArray{T}(undef, (PaddedMatrices.static_length(indices), StaticInt{32}()))
    U_re = StrideArray{T}(undef, (PaddedMatrices.size(U, StaticInt{1}()), PaddedMatrices.size(U, StaticInt{2}())))
    U_im = StrideArray{T}(undef, (PaddedMatrices.size(U, StaticInt{1}()), PaddedMatrices.size(U, StaticInt{2}())))

must be known at compile time. If a dimension is an integer instead of a StaticInt:
julia> typeof(StrideArray{Float64}(undef, (4,5)).data)
Vector{Float64} (alias for Array{Float64, 1})

julia> typeof(StrideArray{Float64}(undef, (StaticInt(4),5)).data)
Vector{Float64} (alias for Array{Float64, 1})

julia> typeof(StrideArray{Float64}(undef, (StaticInt(4),StaticInt(5))).data)
PaddedMatrices.MemoryBuffer{20, Float64}

then the memory of a StrideArray is backed by a regular Vector instead of a mutable struct. mutable structs are stack allocated when they don't escape. PaddedMatrices.@gc_preserve uses GC.@preserve on the mutable struct, and then dumps the memory backing for all StrideArrays being passed to the following call, so that's the recommended approach of avoiding stack allocations when you need to pass them as function arguments but want to keep them stack allocated..
Because U is square, and the length of indices equals the number of rows/columns, I'd probably either picking one of these tw to be statically sized, or passing in a Val or StaticInt argument, and then being sure to use this static size everywhere/for all the initializations.
You could also use
julia> PaddedMatrices.ArrayInterface.indices((C,C,C,C,A), (StaticInt(1),StaticInt(2),StaticInt(2),StaticInt(1),StaticInt(2)))
Base.Slice(StaticInt{1}():StaticInt{1}():StaticInt{8}())

julia> PaddedMatrices.static_length(ans)
StaticInt{8}()

indices here takes a tuple of arrays, and then a tuple of which dim you want to iterate across.
It checks that all the corresponding axes are equal, and also promotes dynamic -> static size, so that if any of the axes happen to be statically sized, it'd return a static range.
You could of course implement simple checks yourself. You may also not want to skip checks on equality if you already know the axes are equal. Maybe we should wrap the equality checks in @boundscheck.
julia> using PaddedMatrices, StaticArrays

julia> A = @StrideArray rand(8,8);

julia> B = @MArray rand(8,8);

julia> C = rand(8,8);

julia> PaddedMatrices.size.((A, B, C))
((StaticInt{8}(), StaticInt{8}()), (StaticInt{8}(), StaticInt{8}()), (8, 8))

julia> PaddedMatrices.size.((A, B, C), StaticInt(1))
(StaticInt{8}(), StaticInt{8}(), 8)

julia> PaddedMatrices.size.((A, B, C), StaticInt(2))
(StaticInt{8}(), StaticInt{8}(), 8)

julia> PaddedMatrices.size === PaddedMatrices.ArrayInterface.size # size is defined in `ArrayInterface
true

julia> PaddedMatrices.size === Base.size
false

That also means that because your U was dynamically sized:
@avx for n ∈ 1:32, m ∈ axes(U, 1)
    C_re_m_n = zero(T)
    C_im_m_n = zero(T)
    for i ∈ axes(U, 2)

both the m ∈ axes(U, 1) and for i ∈ axes(U, 2) loops were dynamically sized.
This probably makes a sizeable difference at small sizes. E.g., the dynamically sized arrays were much slower than the the fixed size array at 4x4 in the PaddedMatrices README. In the first chart, the green line (jmul!) was dynamic, while the orange and blue (PtrArray and StrideArray) were static.
The other two charts have outdated names, but the DynamicMatmul was dynamic and FixedSizeArray, PtrArray, and PaddedArray were static.
PaddedMatrices does introduce a small amount of overhead on top of raw @avx, so the difference at 4x4 would be a bit smaller if all you do is that.
So my suggestions are:

Make sure all the temporaries are statically sized and stack allocated.
Make all the loops statically sized when possible. Assuming you've done 1., you could then simply make the appropriate change in all six occurances:

@avx for n ∈ 1:32, m ∈ axes(U_re, 1)
    C_re_m_n = zero(T)
    C_im_m_n = zero(T)
    for i ∈ axes(U_re, 2)

This may have also influenced the block sizes you found to be optimal.
But, honestly, I only tried 8. So maybe bigger is better.

I have to change the implementation a bit since I need to generate the subspace indices on the fly (the subspace and comspace function), I'll post a repo link later for the utils of creating subspace object so one can reproduce the benchmark I list here.

Okay, I'll try if you provide those functions.

Thanks! It took me a while to wrap up things, but I just posted them in a repo - it will be the next gen simulator backend for Yao.jl and perhaps also will be used by OMEinsum: https://github.com/Roger-luo/BQCESubroutine.jl
I realize this could be quite useful in various areas and since it's not something implemented by BLAS, it can be quite a nice show case for LoopVectorization.
You can find top level routine broutine!'s benchmark here: https://github.com/Roger-luo/BQCESubroutine.jl/blob/master/benchmarks/instruct.jl
regarding this issue, you can find the benchmark scripts here: https://github.com/Roger-luo/BQCESubroutine.jl/blob/master/benchmarks/subspace_mm.jl
where the bcomspace and bsubspace functions are provided by BQCESubroutine.Utilities module.
I'm not sure if it's the best way, but I currently force a re-compilation on the size of U here: https://github.com/Roger-luo/BQCESubroutine.jl/blob/master/src/mul.jl#L22
I also changed the interface convention of st when it's a matrix - so now the b dimension is always the first dimension and is continuous, so I also changed the implementation of yours accordingly. This also makes the StaticArray version faster.
But I find @avx version of subspace_mul_generic! is still slower at small U size which is 4x4 comparing to the manually unrolled version. On the other hand, when U is of size 8x8 it seems to have no improvement comparing to SA version (since SA version is now faster by changing the layout). I'm not sure if there are still space for optimizing its performance, but any other size seems to be pretty good now.

Thanks! It took me a while to wrap up things, but I just posted them in a repo - it will be the next gen simulator backend for Yao.jl and perhaps also will be used by OMEinsum: https://github.com/Roger-luo/BQCESubroutine.jl
I realize this could be quite useful in various areas and since it's not something implemented by BLAS, it can be quite a nice show case for LoopVectorization.
You can find top level routine broutine!'s benchmark here: https://github.com/Roger-luo/BQCESubroutine.jl/blob/master/benchmarks/instruct.jl
regarding this issue, you can find the benchmark scripts here: https://github.com/Roger-luo/BQCESubroutine.jl/blob/master/benchmarks/subspace_mm.jl
where the bcomspace and bsubspace functions are provided by BQCESubroutine.Utilities module.
I'm not sure if it's the best way, but I currently force a re-compilation on the size of U here: https://github.com/Roger-luo/BQCESubroutine.jl/blob/master/src/mul.jl#L22
I also changed the interface convention of st when it's a matrix - so now the b dimension is always the first dimension and is continuous, so I also changed the implementation of yours accordingly. This also makes the StaticArray version faster.
But I find @avx version of subspace_mul_generic! is still slower at small U size which is 4x4 comparing to the manually unrolled version. On the other hand, when U is of size 8x8 it seems to have no improvement comparing to SA version (since SA version is now faster by changing the layout). I'm not sure if there are still space for optimizing its performance, but any other size seems to be pretty good now.

@chriselrod so I just fixed the implementation in BQCESubroutine, however, I realize currently I can only do multithreading in the outermost loop at the moment with the current implementation, since the @avx is called inside the outer loop, but there are a case when the first dimension is larger, then to make use of all the threads one may want to also make the second loop (the B loop: https://github.com/QuantumBFS/BQCESubroutine.jl/blob/master/src/mul.jl#L146), I'm wondering if I could use @avxt in the latest LoopVectorization for this somehow? I'm not sure what has been improved or if there are any of the limitations listed above got resolved.

I tried to remove the reinterpret and use a 3-dim StrideArray directly then reinterpret that later outside (to make the multithreaded code simpler), so I get the following implementation, however this is slower comparing to the original one, and somehow even I moved the temporary array C out and make every dim static, this function still allocates...
using StrideArrays
using ArrayInterface
using LoopVectorization
using YaoLocations
using BenchmarkTools
using BQCESubroutine
using StrideArrays
using BQCESubroutine.Utilities
using LoopVectorization
using ThreadingUtilities
using BQCESubroutine.Utilities: BitSubspace

function subspace_mul_generic!(S::AbstractStrideArray{<:Any, <:Any, T, 3}, indices, C, U::AbstractStrideArray{<:Any, <:Any, T, 3}, subspace, offset=0) where {T <: Base.HWReal}
    Bmax = size(S, 2)
    for s in 1:length(subspace)
        k = subspace[s]
        # idx = k .+ indices
        # _k = k - 1
        for _b ∈ 0:(Bmax-1) >>> 3
            b =    _b << 3;
            bmax = b + 8
            if bmax ≤ Bmax # full static block
                @avx for n ∈ 1:8, m ∈ axes(U, 2)
                    C_re_m_n = zero(T)
                    C_im_m_n = zero(T)
                    for i ∈ axes(U, 3)
                        j = k + indices[i] + offset
                        C_re_m_n += U[1,m,i] * S[1,n+b,j] - U[2,m,i] * S[2,n+b,j]
                        C_im_m_n += U[1,m,i] * S[2,n+b,j] + U[2,m,i] * S[1,n+b,j]
                    end
                    C[1,m,n] = C_re_m_n
                    C[2,m,n] = C_im_m_n
                end
                @avx for n ∈ 1:8, m ∈ axes(U, 2)
                    j = k + indices[m] + offset
                    S[1,n+b,j] = C[1,m,n]
                    S[2,n+b,j] = C[2,m,n]
                end
                # AmulB!(C_re, C_im, U_re, U_im,
            else # dynamic block
                Nmax = 8 + Bmax - bmax
                @avx for n ∈ 1:Nmax, m ∈ axes(U, 2)
                    C_re_m_n = zero(T)
                    C_im_m_n = zero(T)
                    for i ∈ axes(U, 3)
                        j = k + indices[i] + offset
                        C_re_m_n += U[1,m,i] * S[1,n+b,j] - U[2,m,i] * S[2,n+b,j]
                        C_im_m_n += U[1,m,i] * S[2,n+b,j] + U[2,m,i] * S[1,n+b,j]
                    end
                    C[1,m,n] = C_re_m_n
                    C[2,m,n] = C_im_m_n
                end
                @avx for n ∈ 1:Nmax, m ∈ axes(U, 2)
                    j = k + indices[m] + offset
                    S[1,n+b,j] = C[1,m,n]
                    S[2,n+b,j] = C[2,m,n]
                end
            end
        end
    end
    return S
end

S = @StrideArray rand(Float64, 2, 100, 1<<20)
U = @StrideArray rand(Float64, 2, 8, 8)
C = StrideArray{Float64}(undef, (StaticInt{2}(), ArrayInterface.size(U, 2), StaticInt{8}()))
locs = Locations((1, 3, 5))
subspace = bsubspace(20, locs)
comspace = bcomspace(20, locs)
indices = StrideArray{Int}(undef, (StaticInt{length(comspace)}(), ))
@simd ivdep for i in eachindex(indices)
    indices[i] = comspace[i] + 1
end

@benchmark subspace_mul_generic!($(copy(S)), indices, C, U, subspace)

and somehow even I moved the temporary array C out and make every dim static, this function still allocates...

julia> @benchmark subspace_mul_generic!($(copy(S)), indices, C, U, subspace)
BenchmarkTools.Trial:
  memory estimate:  64 bytes
  allocs estimate:  2
  --------------
  minimum time:     196.039 ms (0.00% GC)
  median time:      199.733 ms (0.00% GC)
  mean time:        200.059 ms (0.00% GC)
  maximum time:     206.663 ms (0.00% GC)
  --------------
  samples:          25
  evals/sample:     1

julia> @benchmark subspace_mul_generic!($(copy(S)), $indices, $C, $U, $subspace)
BenchmarkTools.Trial:
  memory estimate:  0 bytes
  allocs estimate:  0
  --------------
  minimum time:     196.955 ms (0.00% GC)
  median time:      200.818 ms (0.00% GC)
  mean time:        201.524 ms (0.00% GC)
  maximum time:     208.475 ms (0.00% GC)
  --------------
  samples:          25
  evals/sample:     1

Sometimes not interpolating doesn't allocate. Sometimes it does.
Have a recent version splitting U to compare with?
I was extremely concerned when I noticed it now takes 200 milliseconds, while the earlier reported times were all around 200 microseconds, but seems we're now doing 4096 times the work?
julia> length(subspace)
131072

julia> subspace_old = [0, 2, 16, 18, 32, 34, 48, 50, 64, 66, 80, 82, 96, 98, 112, 114, 128, 130, 144, 146, 160, 162, 176, 178, 192, 194, 208, 210, 224, 226, 240, 242];

julia> length(subspace_old)
32

julia> length(subspace) / ans
4096.0

LoopVectorization seems to be doing the right thing here based on
julia> ls = let k = 1, offset = 1, b = 1
           LoopVectorization.@avx_debug for n ∈ 1:8, m ∈ axes(U, 2)
                           C_re_m_n = zero(T)
                           C_im_m_n = zero(T)
                           for i ∈ axes(U, 3)
                               j = k + indices[i] + offset
                               C_re_m_n += U[1,m,i] * S[1,n+b,j] - U[2,m,i] * S[2,n+b,j]
                               C_im_m_n += U[1,m,i] * S[2,n+b,j] + U[2,m,i] * S[1,n+b,j]
                           end
                           C[1,m,n] = C_re_m_n
                           C[2,m,n] = C_im_m_n
                      end; end

at least on my computer. But there could be codegen problems in VectorizationBase.
Note that it still has to shuffle on loads from U and stores to C.
LoopVectorization is going to do the wrong thing here, though:
                @avx for n ∈ 1:8, m ∈ axes(U, 2)
                    j = k + indices[m] + offset
                    S[1,n+b,j] = C[1,m,n]
                    S[2,n+b,j] = C[2,m,n]
                end

in that it'll shuffle on loads from C and shuffle again on stores to S. The shuffling isn't necessary. Small chance LLVM is smart enough to see through this and remove the shuffles, but I wouldn't bet on it.
My suggested fix here is to make C be M x 2 x N so that you no longer need to shuffle on the stores to/loads from C, instead only shuffling on the store to S.
Because we're still shuffling on the loads from U, it may also still be worth splitting U into U_re and U_im, or into (like my suggestion for C, make it a 3d array with the second axis real vs imaginary instead of the first).
Shuffling is much faster than gather/scatter like it used to do, but it's still slower than contiguous stores.
So the question is at what point do we reuse loads from U often enough that it becomes profitable to create the temporary.

@Roger-luo
If you have the FMA instruction set, this should be fast:
julia> @time using StaticArrays
@time using Stride  2.432350 seconds (3.14 M allocations: 218.145 MiB, 2.46% gc time)

julia> @time using StrideArrays, LoopVectorization
  9.346095 seconds (7.05 M allocations: 407.005 MiB, 4.09% gc time, 13.52% compilation time)

julia> function cmatmul_array_v2!(Cc::AbstractMatrix{Complex{T}}, Ac::AbstractMatrix{Complex{T}}, Bc::AbstractMatrix{Complex{T}}) where {T}
         C = reinterpret(Float64, Cc);
         A = reinterpret(Float64, Ac);
         B = reinterpret(reshape, Float64, Bc);
         @turbo vectorize=2 for n ∈ indices((C,B),(2,3)), m ∈ indices((C,A),1)
             Cmn = zero(T)
             for k ∈ indices((A,B),(2,2))
                 Amk = A[m,k]
                 Aperm = vpermilps177(Amk)
                 Cmn = vfmaddsub(Amk, B[1,k,n], vfmaddsub(Aperm, B[2,k,n], Cmn))
             end
             C[m,n] = Cmn
         end
         return Cc
     end
Ascmatmul_array_v2! (generic function with 1 method)

julia> As4x4 = @SMatrix rand(4,4);

julia> Bs4x4 = @SMatrix rand(4,4);

julia> Ax4 = StrideArray(MArray(As4x4));

julia> Bx4 = StrideArray(MArray(As4x4));

julia> As4x4 = @SMatrix rand(Complex{Float64},4,4);

julia> Bs4x4 = @SMatrix rand(Complex{Float64},4,4);

julia> Ax4 = StrideArray(MArray(As4x4));

julia> Bx4 = StrideArray(MArray(Bs4x4));

julia> Cx4 = similar(Ax4);

julia> cmatmul_array_v2!(Cx4, Ax4, Bx4)
4×4 StrideArraysCore.StaticStrideArray{Tuple{StaticInt{4}, StaticInt{4}}, (true, true), ComplexF64, 2, 1, 0, (1, 2), Tuple{StaticInt{16}, StaticInt{64}}, Tuple{StaticInt{1}, StaticInt{1}}, 16}:
 -0.206183+1.25759im    0.085368+1.3882im    -0.187353+1.02114im   -0.0220778+2.66172im
  0.167889+1.26523im    0.762005+1.76983im   0.0499955+0.905538im    0.476644+2.13508im
  0.443334+1.56142im    0.712381+2.25556im   0.0856212+1.62122im   -0.0968986+3.11118im
 -0.268315+0.769231im  -0.348635+0.903132im  -0.294804+0.568038im   -0.041956+0.731687im

julia> As4x4 * Bs4x4
4×4 SMatrix{4, 4, ComplexF64, 16} with indices SOneTo(4)×SOneTo(4):
 -0.206183+1.25759im    0.085368+1.3882im    -0.187353+1.02114im   -0.0220778+2.66172im
  0.167889+1.26523im    0.762005+1.76983im   0.0499955+0.905538im    0.476644+2.13508im
  0.443334+1.56142im    0.712381+2.25556im   0.0856212+1.62122im   -0.0968986+3.11118im
 -0.268315+0.769231im  -0.348635+0.903132im  -0.294804+0.568038im   -0.041956+0.731687im

julia> @benchmark $(Ref(As4x4))[] * $(Ref(Bs4x4))[]
BechmarkTools.Trial: 10000 samples with 898 evaluations.
 Range (min … max):  124.272 ns … 227.732 ns  ┊ GC (min … max): 0.00% … 0.00%
 Time  (median):     125.772 ns               ┊ GC (median):    0.00%
 Time  (mean ± σ):   127.029 ns ±   6.736 ns  ┊ GC (mean ± σ):  0.00% ± 0.00%

  ▁▄▆▇█▇▆▅▄▂▅▁▄   ▂▂▂▃▃▃▃▂▁▂                                    ▂
  ██████████████▇██████████████▅▅▅▃▃▁▄▃▅▄▅▅▃▄▄▄▁▄▅▅▃▅▄▄▄▅▃▁▃▁▃▄ █
  124 ns        Histogram: log(frequency) by time        142 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

julia> @benchmark cmatmul_array_v2!($Cx4, $Ax4, $Bx4)
BechmarkTools.Trial: 10000 samples with 995 evaluations.
 Range (min … max):  25.990 ns … 47.732 ns  ┊ GC (min … max): 0.00% … 0.00%
 Time  (median):     26.046 ns              ┊ GC (median):    0.00%
 Time  (mean ± σ):   26.376 ns ±  2.249 ns  ┊ GC (mean ± σ):  0.00% ± 0.00%

  █                                                           ▁
  █▁▃▁▃▁▁▁▃▁▁▆▆▄▄▁▃▄▃▁▁▄▄▅▄▄▄▅▄▃▄▄▃▁▃▃▁▄▁▃▃▁▁▁▃▁▁▃▁▁▁▁▁▁▁▁▃▃█ █
  26 ns        Histogram: log(frequency) by time      43.3 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

julia> versioninfo()
Julia Version 1.6.2-pre.59
Commit 134c34397c (2021-07-01 10:27 UTC)
Platform Info:
  OS: Linux (x86_64-linux-gnu)
  CPU: Intel(R) Core(TM) i3-4010U CPU @ 1.70GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-11.0.1 (ORCJIT, haswell)

Zulip discussion/explanation here.
AVX512 benchmarks:
julia> @benchmark $(Ref(As4x4))[] * $(Ref(Bs4x4))[]
BechmarkTools.Trial: 10000 samples with 989 evaluations.
 Range (min … max):  49.047 ns … 92.030 ns  ┊ GC (min … max): 0.00% … 0.00%
 Time  (median):     49.218 ns              ┊ GC (median):    0.00%
 Time  (mean ± σ):   49.332 ns ±  1.035 ns  ┊ GC (mean ± σ):  0.00% ± 0.00%

    ▁▄▇██▆▄▁   ▂▃▄▃▁                              ▁▁▁         ▂
  ▅▇████████▆▇▇█████▆▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▃▄▅▇▇██████▇▄▆▇▆▇▆ █
  49 ns        Histogram: log(frequency) by time      50.7 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

julia> @benchmark cmatmul_array_v2!($Cx4, $Ax4, $Bx4)
BechmarkTools.Trial: 10000 samples with 999 evaluations.
 Range (min … max):  7.068 ns … 42.729 ns  ┊ GC (min … max): 0.00% … 0.00%
 Time  (median):     7.106 ns              ┊ GC (median):    0.00%
 Time  (mean ± σ):   7.128 ns ±  0.544 ns  ┊ GC (mean ± σ):  0.00% ± 0.00%

                                  ▁▂▄▅▅▇ ▇█▇▆▅▄▃▂▁
  ▂▂▁▁▁▁▁▁▁▁▁▁▁▁▂▁▁▁▁▁▂▂▂▂▂▃▃▄▄▅▇███████▁█████████▇▆▅▄▃▃▃▃▂▂ ▄
  770 ns         Histogram: frequency by time        7.12 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

julia> versioninfo()
Julia Version 1.6.2-pre.2
Commit ff1827d117* (2021-05-02 02:37 UTC)
Platform Info:
  OS: Linux (x86_64-generic-linux)
  CPU: Intel(R) Core(TM) i9-10980XE CPU @ 3.00GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-11.0.1 (ORCJIT, cascadelake)

Note that this implementation is however much slower on CPUs that don't have the FMA instruction set (i.e., specifically the FMA instruction set, as that provides the vfmaddsub instruction). I'll eventually get LoopVectorization to do this automatically so that code can still be written in an architecture-generic manner.

thanks! this is amazing! is there a way to detect FMA instruction set as a global option during precompile then? I think I could also just put this to a @static macro so that on FMA machines we get the maximal performance.

thanks! this is amazing! is there a way to detect FMA instruction set as a global option during precompile then? I think I could also just put this to a @static macro so that on FMA machines we get the maximal performance.

The approach I've been using is
using VectorizationBase
function foo(x, y, z)
   foo_maybefma(x, y, z, VectorizationBase.has_feature(Val(:x86_64_fma)))
end
function foo_maybefma(x, y, z, ::True)
    # implementation requiring FMA
end
function foo_maybefma(x, y, z, ::False)
    # implementation not requiring FMA
end

When you using VectorizationBase, it checks whether every has_feature method is correct, and then @eval updates them if they're wrong.
The motivation for this approach is that the CPU that precompiles might not be the CPU that runs the code later.
The two most common examples are:

Distributing system images.
Beowulf cluster with a network filesystem.

True and False are types defined in Static.jl, so dispatch/methods are all still resolved at compile time; if compiled into a system image, these methods should get invalidated if any has_feature they depend on gets redefined.


ppxAs Bucklescript parser fix

Right now it seems that using the @ppxAs directive is broken. The generated type definitions reference the given type directly, whereas the generated parser tries to access the (not in actuality) generated typename.
An example is the already present record.re test operation.
type scalars  = {
  string,
  int,
};
module MyQuery = [%graphql
  {|
  {
    variousScalars @bsRecord @ppxAs(type: "scalars") {
      string
      int
    }
  }
|}
];

Generates:
// ...
module Raw = {
  type t = {variousScalars: scalars};
};
// ...
type t = {variousScalars: scalars};
// ...
let value = (value: Raw.t).variousScalars;
(
  {

    string: {
      let value = (value: Raw.t_variousScalars).string;

      value;
    },
// ...

Raw.t_variousScalars can not be accessed and throws an error, as that type is never generated as an alias.
I have attempted to introduce a small fix for this in this PR. This solutions works for record generation, but object / legacy do not work with this.
Probably not much more is needed, so I'd be happy about suggestions / locations in the code to check out.

Thanks! I'll leave this open to add the same fix for objects before merging, otherwise I might forget to do that :).

Fixed in https://github.com/reasonml-community/graphql_ppx/commit/cc559c6d9e0b16596eb39f644a2a3603c3555145. Couldn't reconcile git history, sorry :/


Uncaught Error: Unexpected value 'DecoratorFactory' imported by the module 'AppModule'. Please add a @NgModule annotation.

Augury: 1.19.1
Date: Thu, 07 Jun 2018 21:01:28 GMT
OS: Win32
Demo test application:
-- Git repository for demo app showing the issue (optional but very helpful for difficult issues).
-- If a code snippet will completely show the issue, please include it.
Description of issue:
-- Include (clipped) screenshot images if possible.
Angular version (required): ???
Steps to reproduce:

Additional details:

Hi thanks for the report. We're about to push a few bugfixes as a Canary release. Please review your issue using this release, and if this problem continues, please create a new issue including steps to reproduce and some details about your environment.
Thank you,
Ken


QUESTION: Parenting bodies

First of all, amazing work so far <3.
I was wondering if there is support for parenting bodies with a stiff connection (not welding).
Currently in the game we want to be able to move props (bodies) inside of a ship, but have the ship move all the bodies inside of it (parented).
Kinda how unity does transforms :

Maybe a container body type? That acts as a sub-world

The feature you want looks like scene hierarchy. I think this is more of a game engine feature than a physics engine feature.
You can implement this like after a physics update, recursively reposition the child's transform relative to the parent's local transform (which is registerd in physics engine).
Check out this article!: https://learnopengl.com/Guest-Articles/2021/Scene/Scene-Graph

The feature you want looks like scene hierarchy. I think this is more of a game engine feature than a physics engine feature.
You can implement this like after a physics update, recursively reposition the child's transform relative to the parent's local transform (which is registerd in physics engine).
Check out this article!: https://learnopengl.com/Guest-Articles/2021/Scene/Scene-Graph

Will take a look :D, thanks!


No roles have permission to run the -WhatIf parameter with Delete-QuarantineMessage

The -WhatIf parameter doesn't work with this cmdlet. It throws the following error message:
Write-ErrorMessage : ExB880D8|Microsoft.Exchange.Configuration.Authorization.CmdletAccessDeniedException|The "WhatIf" parameter can't be used on the "Delete-QuarantineMessage" cmdlet because it isn't present in the role definition for the current user. Check the management roles assigned to you, and try again.
At C:\Users\XXX\AppData\Local\Temp\169\tmpEXO_dzngcuhj.cph\tmpEXO_dzngcuhj.cph.psm1:1190 char:13
+             Write-ErrorMessage $ErrorObject
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : PermissionDenied: (:) [Delete-QuarantineMessage], CmdletAccessDeniedException
    + FullyQualifiedErrorId : [Server=DB5PR10MB7666,RequestId=1a669ad2-0a06-fcd0-ea1e-d25c20e7f623,TimeStamp=Wed, 25 Oct 2023 08:55:38 GMT],Write-ErrorMessage

It seems that there are no roles with permission to run the cmdlet with this parameter Running the following commands gives no result:
$Perms = Get-ManagementRole -Cmdlet Delete-QuarantineMessage -CmdletParameters WhatIf
$Perms | foreach {Get-ManagementRoleAssignment -Role $_.Name -Delegating $false | Format-Table -Auto Role,RoleAssigneeType,RoleAssigneeName}

For reference I ran them for another parameter and got the expected result:
$Perms = Get-ManagementRole -Cmdlet Delete-QuarantineMessage -CmdletParameters HardDelete
$Perms | foreach {Get-ManagementRoleAssignment -Role $_.Name -Delegating $false | Format-Table -Auto Role,RoleAssigneeType,RoleAssigneeName}

Role              RoleAssigneeType RoleAssigneeName
----              ---------------- ----------------
Transport Hygiene RoleGroup        Hygiene Management
Transport Hygiene RoleGroup        Organization Management

Role           RoleAssigneeType RoleAssigneeName
----           ---------------- ----------------
Security Admin RoleGroup        Organization Management
Security Admin RoleGroup        SecurityAdmins_-21872738

Document Details
⚠ Do not edit this section. It is required for learn.microsoft.com ➟ GitHub issue linking.

ID: 54c93f73-0b14-ae66-5f31-c60f86dcfc40
Version Independent ID: d8c0aa20-0abd-5766-f437-18f884ffc3ab
Content: Delete-QuarantineMessage (ExchangePowerShell)
Content Source: exchange/exchange-ps/exchange/Delete-QuarantineMessage.md
Service: exchange-powershell
GitHub Login: @chrisda
Microsoft Alias: chrisda

@frbjly, I presume you were in Exchange Online PowerShell and not in Security & Compliance PowerShell? The WhatIf switch doesn't work for any cmdlet in Security & Compliance PowerShell, and the affected articles say so (including this one):

The WhatIf switch simulates the actions of the command. You can use this switch to view the changes that would occur without actually applying those changes. You don't need to specify a value with this switch.
The WhatIf switch doesn't work in Security & Compliance PowerShell.

@chrisda, That is correct, I am using Exchange Online PowerShell - not Security & Compliance PowerShell. For reference I checked what the output is if I run the same commands for the "Release-QuarantineMessage" cmdlet (which has the same limitation regarding Security & Compliance PowerShell) and as you can see the result is different from the one I get for "Delete-QuarantineMessage":
$Perms = Get-ManagementRole -Cmdlet Release-QuarantineMessage -CmdletParameters WhatIf

$Perms | foreach {Get-ManagementRoleAssignment -Role $_.Name -Delegating $false | Format-Table -Auto Role,RoleAssigneeType,RoleAssigneeName}

Role              RoleAssigneeType RoleAssigneeName
----              ---------------- ----------------
Transport Hygiene RoleGroup        Hygiene Management
Transport Hygiene RoleGroup        Organization Management

Role           RoleAssigneeType RoleAssigneeName
----           ---------------- ----------------
Security Admin RoleGroup        Organization Management
Security Admin RoleGroup        SecurityAdmins_-21872738

@frbjly, OK. Since WhatIf doesn't work in ExO PowerShell or S&C PowerShell, I changed the description to:

This parameter is reserved for internal Microsoft use.

Thanks for the feedback.
Closing


Make sure the shortcut key respects the context in TileSetAtlasSourceEditor

Fix #74061.

Thanks!

Cherry-picked for 4.1.1.


Move composer Ci/CD source to samples

Summary
The Set up continuous integration and continuous delivery for a Composer bot article is labeled as preview and the links in the article point to a personal repo under https://github.com/gabog/ComposerCICDSamples/.
As part if this issue we should remove the Preview label from the article and move the source to the Samples repo under https://github.com/microsoft/BotBuilder-Samples/tree/main/composer-samples/csharp_dotnetcore/projects

This appears to have been done.


[SQL Migration] Add schema migration validation

adding IR version validation. Before going to RP, if users enable schema migration and the IR node doesn't support schema migration, disable the schema migration option. The SQLDB migration validation failure rate will have significant reduction.
Windows login is currently supported in SHIR. Therefore, if users use WIndows auth to connect the source instance for schema mgiration, disable the schema migration option. The SQLDB migration failure due to "login failed for user" will have significant reduction.

In Step 4, adding infor banner

In Step 6, check the IR nodes version and windows login. If true, show the warning message on the top and disable the schema migration option.

Pull Request Test Coverage Report for Build<PHONE_NUMBER>

0 of 0   changed or added relevant lines in 0 files are covered.
1 unchanged line in 1 file lost coverage.
Overall coverage decreased (-0.001%) to 41.603%

Files with Coverage Reduction
New Missed Lines
%

extensions/notebook/src/dialog/configurePython/configurePythonWizard.ts
1
46.46%

Totals

Change from base Build<PHONE_NUMBER>:
-0.001%

Covered Lines:
30817

Relevant Lines:
69389

💛  - Coveralls


[backport] [1.2] [plugin] repository-azure is not working properly hangs on basic operations

Signed-off-by: Andriy Redko<EMAIL_ADDRESS>Description
Backport of https://github.com/opensearch-project/OpenSearch/pull/1740 to 1.2
Issues Resolved
Closes https://github.com/opensearch-project/OpenSearch/issues/1734
Check List

[ ] New functionality includes testing.

[ ] All tests pass

[ ] New functionality has been documented.

[ ] New functionality has javadoc added

[X] Commits are signed per the DCO using --signoff

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

Let’s wait on merging this to 1.2 for a short minute until 1.2.2 is released. I don’t think we want to hold a security patch for a feature regression.

Btw, if we can address https://github.com/opensearch-project/OpenSearch/issues/1707 we can significantly reduce the amount of work to do a 1.2.3 (no need to rebuild plugins at all). @nknize could use a comment from you on whether that’s by design or we can relax it.


Gray scale training, "input shape" error message

Does this model support gray-scale (1D) training ?
To train gray scale training images, I add "c_dim" parameter on train code like below
rdn = RDN(arch_params={'C':6, 'D':20, 'G':64, 'G0':64, 'x':scale}, patch_size=lr_train_patch_size, c_dim=1)
But, I got below error message
ValueError: Input 0 of layer Conv_1 is incompatible with the layer: expected axis -1 of input shape to have value 3 but received input with shape [None, 64, 64, 1]
This is my code.
from ISR.models import RDN
from ISR.models import Discriminator
from ISR.models import Cut_VGG19

lr_train_patch_size = 32
layers_to_extract = [5, 9]
scale = 2
hr_train_patch_size = lr_train_patch_size * scale

rdn = RDN(arch_params={'C':6, 'D':20, 'G':64, 'G0':64, 'x':scale}, patch_size=lr_train_patch_size, c_dim=1)
f_ext = Cut_VGG19(patch_size=hr_train_patch_size, layers_to_extract=layers_to_extract)
discr = Discriminator(patch_size=hr_train_patch_size, kernel_size=3)

from ISR.train import Trainer
loss_weights = {
  'generator': 0.0,
  'feature_extractor': 0.08333,
  'discriminator': 0.01
}
losses = {
  'generator': 'mae',
  'feature_extractor': 'mse',
  'discriminator': 'binary_crossentropy'
}

log_dirs = {'logs': './logs', 'weights': './weights'}
learning_rate = {'initial_value': 0.0004, 'decay_factor': 0.5, 'decay_frequency': 30}
flatness = {'min': 0.0, 'max': 0.15, 'increase': 0.01, 'increase_frequency': 5}

trainer = Trainer(
    generator=rdn,
    discriminator=discr,
    feature_extractor=f_ext,

    lr_train_dir='data/gray/scale_x2/train/LR/',
    hr_train_dir='data/gray/scale_x2/train/HR/',
    lr_valid_dir='data/gray/scale_x2/val/LR/',
    hr_valid_dir='data/gray/scale_x2/val/HR/',

    loss_weights=loss_weights,
    learning_rate=learning_rate,
    flatness=flatness,
    dataname='gray/scale_x2',
    log_dirs=log_dirs,
    metrics={'generator': 'PSNR'},
    weights_generator=None,
    weights_discriminator=None,
    n_validation=100,
)
trainer.train(
    epochs=50,
    steps_per_epoch=100,
    batch_size=20,
    monitored_metrics={'val_generator_loss': 'max'}
)

could you post the entire error logs?


[AVRO-3715]: Make build work again

What is the purpose of the change
The build never passes anymore in Github.
https://issues.apache.org/jira/browse/AVRO-3715

Thank you, @nielsbasjes .