Raster Marginals在朱莉娅洗牌 - 更好的实施

时间:2016-06-23 15:50:00

标签: algorithm julia shuffle

我想实现一个零和一个矩阵的混洗方法,它采用随机的2x2子矩阵,只有当它们的colsums和rowums相等时才翻转它们,即[0 1; 1 0]或[1 0; 0 1]。

编辑:仅供参考,这应该意味着两者

sum(matrix,1) == sum(shuffledmatrix,1) && 
sum(matrix,2) == sum(shuffledmatrix,2)

==>真

下面的代码是正确的,但基本上还不够快。谁能在这里看到任何明显的错误? (我对朱莉娅很新!)

function rastershuffle!(shuffledmatrix::Array{Int32,2},minchanges::Int)
    @inbounds begin
        numchanges = 0
        numcols = size(shuffledmatrix,2)
        numrows = size(shuffledmatrix,1)
        while numchanges < minchanges
            a = findmargeflip!(shuffledmatrix,numcols::Int, numrows::Int)
            numchanges = numchanges + sum(a) 
        end
    end
    return shuffledmatrix
end

function findmargeflip!(shuffledmatrix::Array{Int32,2},numcols::Int, numrows::Int)
    change = false
    cols = EPhys.random_generator(2,numcols)
    rows = EPhys.random_generator(2,numrows)
    vall = sub(shuffledmatrix, [rows[1]; rows[2]],[cols[1]; cols[2]])
    if vall == [0 1; 1 0] || vall == [1 0; 0 1]
        flipvall!(vall)
        #numchanges += 1
        change = true
    end
    change
end

function flipvall!(vall)
    if vall[1] == 1
        vall[:] = [0 1 1 0]    
    else
        vall[:] = [1 0 0 1]
    end
    nothing
end

到目前为止,我根据文档中的信息尝试了什么:

  • 使用BitArrays而不是Int32 - 虽然我可能会改变它,但是功能却没有太大的区别!也可以用flipbits代替!

  • 为编译器提供额外的类型信息

  • 设置迭代次数而不是更改,然后尝试使用@simd进行矢量化

我认为主要瓶颈是每次迭代重新生成SubArray,这需要内存重新分配/垃圾收集,但我不完全确定如何绕过它。

额外信息:

shuffledspikematrix3 = copy(spikematrixnonoise)
@time rastershuffle!(shuffledspikematrix3, 100);
@profile rastershuffle!(shuffledspikematrix3, 100);
Profile.print()

===&GT;输出:

 8.776213 seconds (153.35 M allocations: 7.835 GB, 15.94% gc time)
    1   abstractarray.jl; ==; line: 1060
    1   abstractarray.jl; hvcat; line: 974
    2   abstractarray.jl; vcat; line: 733
    2   array.jl; getindex; line: 282
    2   multidimensional.jl; start; line: 99
    800 task.jl; anonymous; line: 447
     800 .../IJulia/src/IJulia.jl; eventloop; line: 143
      800 ...rc/execute_request.jl; execute_request_0x535c5df2; line: 183
       800 loading.jl; include_string; line: 266
        800 profile.jl; anonymous; line: 16
         800 In[174]; rastershuffle!; line: 7
          1   ...devel/src/helper.jl; random_generator; line: 52
          1   In[174]; findmargeflip!; line: 15
          77  In[174]; findmargeflip!; line: 16
           13 ....devel/src/helper.jl; random_generator; line: 44
            7 random.jl; rand; line: 255
             5 random.jl; gen_rand; line: 88
              1 dSFMT.jl; dsfmt_fill_array_close1_open2!; line: 66
              4 dSFMT.jl; dsfmt_fill_array_close1_open2!; line: 67
            2 random.jl; rand; line: 256
           47 ....devel/src/helper.jl; random_generator; line: 47
           1  ....devel/src/helper.jl; random_generator; line: 48
           13 ....devel/src/helper.jl; random_generator; line: 49
           1  ....devel/src/helper.jl; random_generator; line: 52
          86  In[174]; findmargeflip!; line: 17
           9  ....devel/src/helper.jl; random_generator; line: 44
            5 random.jl; rand; line: 255
             4 random.jl; gen_rand; line: 88
              4 dSFMT.jl; dsfmt_fill_array_close1_open2!; line: 67
            1 random.jl; rand; line: 256
           53 ....devel/src/helper.jl; random_generator; line: 47
           1  ....devel/src/helper.jl; random_generator; line: 48
           13 ....devel/src/helper.jl; random_generator; line: 49
           2  ....devel/src/helper.jl; random_generator; line: 52
          211 In[174]; findmargeflip!; line: 19
           87 abstractarray.jl; vcat; line: 733
           9  subarray.jl; _sub; line: 90
           35 subarray.jl; _sub; line: 91
            1  subarray.jl; _sub_unsafe; line: 96
            21 subarray.jl; _sub_unsafe; line: 125
            1  subarray.jl; _sub_unsafe; line: 437
            1  subarray.jl; _sub_unsafe; line: 440
          411 In[174]; findmargeflip!; line: 20
           5   abstractarray.jl; ==; line: 1060
           4   abstractarray.jl; ==; line: 1066
           258 abstractarray.jl; ==; line: 1067
           4   abstractarray.jl; ==; line: 1068
           2   abstractarray.jl; hvcat; line: 957
           87  abstractarray.jl; hvcat; line: 960
           1   abstractarray.jl; hvcat; line: 961
           2   abstractarray.jl; hvcat; line: 969
           3   abstractarray.jl; hvcat; line: 970
           11  abstractarray.jl; hvcat; line: 971
           1   abstractarray.jl; hvcat; line: 974
          4   In[174]; findmargeflip!; line: 25
          1   abstractarray.jl; ==; line: 1060
          2   abstractarray.jl; hvcat; line: 960
          1   abstractarray.jl; vcat; line: 733
    1   tuple.jl; ==; line: 95
    3   tuple.jl; ==; line: 96

2 个答案:

答案 0 :(得分:4)

分析清楚地告诉你,花在

上的时间最多
211 In[174]; findmargeflip!; line: 19
411 In[174]; findmargeflip!; line: 20

  vall = sub(shuffledmatrix, [rows[1]; rows[2]],[cols[1]; cols[2]])
  if vall == [0 1; 1 0] || vall == [1 0; 0 1]

您正在各地分配新阵列。

尝试使用类似

的内容替换vall == [0 1; 1 0]
 size(val1) == (2,2) && val1[1,1] == 0 &&
     val1[1,2] == 1 && val1[2,1] == 1 && val1[2,2] == 0

顺便说一句,为什么你混合Int32&amp; Int64?为了节省矩阵的记忆?

答案 1 :(得分:1)

这是相同功能的替代实现(如果我理解它的功能是正确的)。它很有可能更快地工作,但它不会使用与OP相同的随机源。看一下,可能会给出优化建议。

希望这有帮助。

#ifndef AWINERY_H
#define AWINERY_H

#include <iostream>
using namespace std;

//winery object
class aWinery
{
public:
    //Constructor
    aWinery();

    //Destructor
    ~aWinery();

    //Accessor Prototypes
    void getName(char name[]) const;
    void getLocation(char location[]) const;
    void getYear(int year) const;
    void getAcres(float acres) const;
    void getSuccessRating(float successRating) const;

    //Mutator Prototypes
    void setName(char name0[]);
    void setLocation(char location0[]);
    void setYear(int year0);
    void setAcres(float acres0);
    void setSuccessRating(float successRating0);


private:
    char* name;
    char* location;
    int* year;
    float* acres;
    float* successRating;
};

#endif

#ifndef ALIST_H #define ALIST_H #include <iostream> using namespace std; const int MAX_CHAR_LENGTH = 1000; class list { public: //Prototypes void setInWinery(char name[], char location[], int year, float acres, float successRating); void initializeDbase(char savePathName[]); void printEntireDbase(); void deleteWinery(char nameOfWinery[]); void whereIsWinery(char nameOfWinery[]); void save(char savePathName[]); //Accessor Prototypes void getWineryName(char name[]) const; void getWineryLocation(char location[]) const; void getWineryYear(int year) const; void getWineryAcres(float acres) const; void getWinerySuccessRating(float successRating) const; int getSize() const; //Mutator Prototypes void setWineryName(char name[]); void setWineryLocation(char location[]); void setWineryYear(int year); void setWineryAcres(float acres); void setWinerySuccessRating(float successRating); //Constructor Prototype list(); //Destructor ~list(); private: //Wine object struct node { aWinery wineryData; node * nextByName; node * nextByRating; }; node * nameHead, * nameTail, * ratingHead, * ratingTail; aWinery wineryData; int size; }; #endif 一起使用,其中function flipit!(m, flipcount) zeroinds = map(x->ind2sub(m,x),find(m .== 0)) # find 0 locations zerorows = Set{Int}(map(first,zeroinds)) # find rows with 0s zerocols = Set{Int}(map(last,zeroinds)) # find cols with 0s oneinds = map(x->ind2sub(m,x),find(m .== 1)) # find 1 locations filter!(x->x[1] in zerorows && x[2] in zerocols,oneinds) # must satisfy trivially n = length(oneinds) numflips = 0 badcount = 0 badcorners = Set{Tuple{Int,Int}}() # track bad rectangles maxbad = binomial(length(oneinds),2) # num candidate rectangles maxbad == 0 && error("Can't find candidate rectangle") randbuf = rand(1:n,2*flipcount) # make some rands to use later while numflips < flipcount if length(randbuf)==0 randbuf = rand(1:n,2*flipcount) # refresh rands end cornersinds = minmax(pop!(randbuf),pop!(randbuf)) if first(cornersinds)==last(cornersinds) continue ; end if cornersinds in badcorners continue # bad candidate end corners = (oneinds[cornersinds[1]],oneinds[cornersinds[2]]) if m[corners[1][1],corners[2][2]] == 0 && # check 0s m[corners[2][1],corners[1][2]] == 0 m[corners[1]...] = 0 # flip m[corners[2]...] = 0 m[corners[1][1],corners[2][2]] = 1 m[corners[2][1],corners[1][2]] = 1 oneinds[cornersinds[1]] = (corners[1][1],corners[2][2]) # flip corner list oneinds[cornersinds[2]] = (corners[2][1],corners[1][2]) numflips += 1 if badcount>0 badcount = 0 empty!(badcorners) end else push!(badcorners,cornersinds) # remember bad candidate badcount += 1 if badcount == maxbad # if candidates exhausted error("No flippable rectangle") end end end end 是矩阵,flipit!(M,n)是所需的翻转次数。这不是最干净的代码,试图更清晰,更紧凑。