Как я могу использовать основные приемы для улучшения моего кода Джулии? - PullRequest
0 голосов
/ 03 мая 2019

Я относительно новичок с Джулией, и сейчас я использую версию 1.0.У меня есть код, который предназначен для создания последовательности целых чисел на основе входной матрицы.Выполнение кода на моей машине занимает 3 часа (i5, двухъядерный, 16 ГБ ОЗУ), используя 16% ЦП и 3% памяти.Есть ли какие-нибудь основные советы, которые я могу выучить и применить для оптимизации своего кода в Julia для повышения его производительности?Влияет ли отступ на производительность?Есть ли пакет, который может отслеживать мой код и предлагать улучшения?Я предоставляю свой код ниже.Код включает в себя код R, который генерирует данные, к которым применим код Джулии.Если во время кода R возникает ошибка, это просто отсутствие достижений во время симуляции, и ее необходимо запустить снова, пока симуляция не будет завершена.

using Distances
using RCall
using Distributions
using BSON: @save, @load
using StatsBase
using LinearAlgebra

R"simul<-function(m){
  comb<-expand.grid(c(0.01,0.2,0.4),
                c(sample(2:7,1),sample(8:12,1),sample(13:20,1)),
                c(sample(2:5,1),sample(6:10,1),sample(11:20,1)),
                c(150,500,1500))
gener<-function(i){
maxoverlap<-comb[i,1]
nbvar<-comb[i,2]
nbclass<-comb[i,3]
propmix<-runif(1,0.001,1/nbclass)
Q<-MixSim(MaxOmega = maxoverlap, K = nbclass, p = nbvar,PiLow = propmix,resN = 1000)
A <- simdataset(n = comb[i,4], Pi = Q$Pi, Mu = Q$Mu, S = Q$S)
results<-list(Q,A)
return(results)
}
donnees<-sapply(1:nrow(comb),gener)
}
library(MixSim)
donneesimul=simul(1)"
@rget donneesimul

function pointsdpp(t)
 datasim=donneesimul[2,t][:X]

 Eucldist=pairwise(Euclidean(),transpose(datasim))
 D=maximum(Eucldist.^2)
 sigma2hat=mean(((Eucldist.^2)./D)[tril!(trues(size((Eucldist.^2)./D)),-1)])
 L=exp.(-(Eucldist.^2/D)/(2*sigma2hat))

 eigenv=eigvals(L)
 prob=eigenv./(eigenv.+1)
 eigenvectors=eigvecs(L)
function sampledpp(m)
u=rand(size(L,1))
V=eigenvectors[:,findall(u.<=prob)]
k=size(V,2)
Y=zeros(Int64,k)
for i=k:-1:1
P=sum(V.^2,dims=2)
Pri=P / sum(P)
Cumpri=cumsum(Pri,dims=1)
u=rand()
Y[i]=findfirst(u.<=Cumpri)[1]
if i==1 break end
j=findfirst(V[Y[i],:].!=0)
Vj=V[:,j]
V=V[:,deleteat!(collect(1:1:size(V,2)),j)]
V=V-repeat(Vj,1,size(V,2)).*repeat(transpose(V[Y[i],:]/Vj[Y[i]]),size(V,1))

for a = 1:i-1
    for b = 1:a-1
      V[:,a] = V[:,a] - transpose(V[:,a])*V[:,b]*V[:,b]
    end
    V[:,a] = V[:,a] / norm(V[:,a])
end
end
Y=sort(Y)
return(Y)
end

m=collect(1:1000)
sampleY_repet=map(sampledpp,m)
end
w=collect(1:1:81)
echantdpp=map(pointsdpp,w)
@save "echantdppdatasim1.bson" echantdpp

1 Ответ

2 голосов
/ 05 мая 2019

Есть много вопросов, которые следует учитывать при оценке производительности Юлия.Хотя предоставленный вами код далеко выходит за рамки MWE (минимальный рабочий пример) и также не воспроизводится.Однако вот некоторые общие рекомендации:

  1. Потратьте некоторое время, чтобы внимательно прочитать Советы по производительности Julia и применить их
  2. Поскольку вы обрабатываете некоторые массивы, ваш код будетвероятная выгода от макроса @simd.Использование представлений массива также очень часто является легким плодом для таких кодов, как ваш.
  3. Вы используете 16% мощности процессора (вероятно, у вас 8 ядер, а ваша программа использует только одно).Подумайте об использовании многопоточности или многопроцессорности - ваша программа будет работать во много раз быстрее
  4. В некоторых случаях вы можете рассмотреть возможность использования вычислений на GPU с Flux.jl
  5. Рассмотреть вопрос о переносе многоядерных вычислений наОблако (масштабирование Джулии на экземплярах AWS EC2 работает просто великолепно)

Поскольку каждая из этих тем представляет собой большую область для пошаговой работы над кодом и задает вопросы, чтобы получить помощь.

...