2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2  След.
 
 Вопрос по оптимизации скрипта [R]
Сообщение02.08.2013, 19:41 


28/03/10
68
Доброго времени суток!

В данный момент пишу диссертацию по геостатистике. Возникла проблема расчета вариограммы. Напомню что вариаграмма считается по формуле:
G=1/2N(h) * Sum[(x1-x2)^2]
где N - это число пар

У меня есть база данных состоящая из 5 колонок, 1ая это имя скважины, 2-3-4 это координаты x, y, z, и 5ая колонка это значение ллюбое (допустим кажущееся сопротивление). Вот как она выглядит:

Имя X Y Z KS
212 25 13 -5 0.5
.........................


И таких строк 28 тысяч.

Я написал скрипт на языке R:

pairs=function(well, h){
k=0
for(i in 1:nrow(well)-1){
for(j in i:nrow(well)){
if(well[i, "Имя"]!=well[j, "Имя"] $ well[i, "Z"]-well[j, "z"]<0.05 &
sqrt((well[i, "Z"]-well[i, "Z"])**2+(well[i, "Z"]-well[i, "Z"])^2+(well[i, "Z"]-well[i, "Z"])^2)<h){
k=k+1
}}}return(k)}

diff=function(well, h){
g=0
for(i in 1:nrow(well)-1){
for(j in i:nrow(well)){
if(well[i, "Имя"]!=well[j, "Имя"] $ well[i, "Z"]-well[j, "z"]<0.05 &
sqrt((well[i, "Z"]-well[i, "Z"])**2+(well[i, "Z"]-well[i, "Z"])^2+(well[i, "Z"]-well[i, "Z"])^2)<h){
g=g+(well[i, "KS"]- well[j, "KS"])^2
}}}return(g)}

c=seq(5,101, by=5)

for(i in c){
var=1/2*pairs(well, i) * diff(well, i)
print(var)}

Условия if там для того чтобы не брать одну и ту же скважину, примерно на одном уровне Z+-5cm, и расстояние было меньше h. Все работает но очень долго. Если кто сможет помочь улучшить алгоритм буду очень признателен. Спасибо!

 Профиль  
                  
 
 Re: Вопрос по оптимазации скрипта
Сообщение02.08.2013, 20:37 
Аватара пользователя


31/10/08
1244
Язык R не знаю. Но общие рекомендации таковы.
1. Отказаться в цикле от именованных массивов в пользу индексных. К примеру завести временные массивы.
2. Вынести условия из цикла.
3. Степень заменить умножением.
4. Алгоритм сам по себе тяжёлый. Квадратичный. Тут нечем не поделаешь.

Цитата:
sqrt((well[i, "Z"]-well[i, "Z"])**2+(well[i, "Z"]-well[i, "Z"])^2+(well[i, "Z"]-well[i, "Z"])^2)<h)

Обычный трюк возвести в квадрат обе части неравенства. Тем самым избавляемся от корня. А h*h вычисляется до цикла. Но возможно это условие стоит выкинуть?
Или использовать разбить всё множество точек решёткой и искать пары только в квадратах это ускорит работу.

Надеюсь R работает с числами двойной точности(double float)

 Профиль  
                  
 
 Re: Вопрос по оптимазации скрипта
Сообщение03.08.2013, 00:26 
Заслуженный участник


16/02/13
4200
Владивосток
Как минимум — слить функции в один цикл, считать сразу количество и сумму. Раза в два быстрее получится.

 Профиль  
                  
 
 Re: Вопрос по оптимазации скрипта
Сообщение03.08.2013, 05:26 
Заслуженный участник


27/04/09
28128
Pavia в сообщении #751401 писал(а):
1. Отказаться в цикле от именованных массивов в пользу индексных. К примеру завести временные массивы.
Это может никак не действовать по многим причинам, так что сгодилось бы, возможно, лишь как последний пункт. («Именованных массивов»? Я думал, это называется нецелочисленные индексы.)

 Профиль  
                  
 
 Re: Вопрос по оптимазации скрипта
Сообщение03.08.2013, 05:39 
Аватара пользователя


20/10/12
308
Можно переписать на C.
А еще можно просто подождать. За выходные, наверно, сосчитает.
Чтобы было не скучно, можно выводить счетчик внешнего цикла.
Железо и электричество нынче дешевы, а труд дорог.

 Профиль  
                  
 
 Re: Вопрос по оптимазации скрипта
Сообщение03.08.2013, 06:24 


28/03/10
68
Pavia в сообщении #751401 писал(а):
Язык R не знаю. Но общие рекомендации таковы.
1. Отказаться в цикле от именованных массивов в пользу индексных. К примеру завести временные массивы.
2. Вынести условия из цикла.
3. Степень заменить умножением.
4. Алгоритм сам по себе тяжёлый. Квадратичный. Тут нечем не поделаешь.

Цитата:
sqrt((well[i, "Z"]-well[i, "Z"])**2+(well[i, "Z"]-well[i, "Z"])^2+(well[i, "Z"]-well[i, "Z"])^2)<h)

Обычный трюк возвести в квадрат обе части неравенства. Тем самым избавляемся от корня. А h*h вычисляется до цикла. Но возможно это условие стоит выкинуть?
Или использовать разбить всё множество точек решёткой и искать пары только в квадратах это ускорит работу.

Надеюсь R работает с числами двойной точности(double float)


Я сам в прораммировании не ас, но разве я не с индексами работаю? Условия из цикла не получится вынести, они должны же на каждой линии проверятся. А так по остальным советам все сделал, прирост не большой.

-- Сб авг 03, 2013 10:33:14 --

Sphinx Pinastri в сообщении #751458 писал(а):
Можно переписать на C.
А еще можно просто подождать. За выходные, наверно, сосчитает.
Чтобы было не скучно, можно выводить счетчик внешнего цикла.
Железо и электричество нынче дешевы, а труд дорог.

C не знаю, лучше знаю питон, но думаю питон будет по слабее с таким объемом данных. R как никак создан для дата анализа. А так на си можно было бы попробовать, но не подскажете как считать данные с формата .csv?

-- Сб авг 03, 2013 10:34:28 --

arseniiv в сообщении #751456 писал(а):
Pavia в сообщении #751401 писал(а):
1. Отказаться в цикле от именованных массивов в пользу индексных. К примеру завести временные массивы.
Это может никак не действовать по многим причинам, так что сгодилось бы, возможно, лишь как последний пункт. («Именованных массивов»? Я думал, это называется нецелочисленные индексы.)

Можно поподробнее про индексные массивы?

-- Сб авг 03, 2013 11:20:44 --

Еще один вопрос. На си можно было в цикле создавать списки с именами по порядку. Например если цикл ну одного до пяти то он создаст пять массивов с именами в1 в2 в3 в4 в5. Как этот прием назывался? Не знаю как запрос в гугле сделать

 Профиль  
                  
 
 Re: Вопрос по оптимазации скрипта
Сообщение03.08.2013, 07:46 
Аватара пользователя


31/10/08
1244
arseniiv в сообщении #751456 писал(а):
«Именованных массивов»? Я думал, это называется нецелочисленные индексы.

Разные авторы по разному, называют. Также это называют ассоциативным массивом.
Наверно правильнее не целочисленные. Просто вчера не смог вспомнить как правильнее.

Alibek24 в сообщении #751460 писал(а):
Можно поподробнее про индексные массивы?

Я считаю что основные тормоза за обращения к массиву well[j, "Имя"]. Да теоретически оптимизатор мог справиться, но мой опыт подсказывает что обычно нет. Так что тут скорее всего основной тормоз прирост должен быть больным.

Массив в котором в качестве индекса используют целые числа работает быстрее нежели чем массив в котором в качестве индекса используют строки.
well[j, "Имя"] ; well[j, "X"]; well[j, "Y"]; well[j, "Z"] надо заменить на 4 массива.
name[j]; X[j]; Y[j]; Z[j]

Alibek24 в сообщении #751460 писал(а):
как считать данные с формата .csv?

Это простой формат. Он является текстовым. Столбцы разделены либо точкой либо точкой с запятой.
Строки разделены стандартным текстовым кодом новой строки - CRLF.

 Профиль  
                  
 
 Re: Вопрос по оптимазации скрипта
Сообщение03.08.2013, 08:35 
Аватара пользователя


20/10/12
308
Вы говорите, что программа работает, но в это верится с трудом.
Почему одно 'z' на нижнем регистре.
Зачем вычитать одинаковые величины. Ясно, что получится 0.
Зачем считать одно и то же много раз.
Код:
if(well[i, "Имя"] != well[j, "Имя"] $
      well[i, "Z"]-well[j, "z"] < 0.05 &
sqrt((well[i, "Z"]-well[i, "Z"])**2 +
     (well[i, "Z"]-well[i, "Z"])^2  +
     (well[i, "Z"]-well[i, "Z"])^2) < h) { ... }

Наверно, этот фрагмент должен быть таким.
Код:
if(well[i, "Имя"] != well[j, "Имя"] $
      well[i, "Z"]-well[j, "Z"] < 0.05 &
sqrt((well[i, "Z"]-well[j, "Z"])**2 +
     (well[i, "X"]-well[j, "X"])^2  +
     (well[i, "Y"]-well[j, "Y"])^2) < h) { ... }

Если можно, опубликуйте данные, а программистов здесь много.

 Профиль  
                  
 
 Re: Вопрос по оптимазации скрипта
Сообщение03.08.2013, 10:46 


28/03/10
68
Может быть где то и ошибся при написании кода, так как она была написана по памяти. Z это координата. для одной скважины таких координат может быть 500 и больше. Мне же надо сравнить данные на одном уровне для всех скважин, в радиусе h. Я проверил для более мелких циклов, работала

 Профиль  
                  
 
 Re: Вопрос по оптимазации скрипта
Сообщение03.08.2013, 17:20 
Аватара пользователя


20/10/12
308
Пожалуйста приведите программу, которая работает.
Поиск опечаток силами форума в том, что написано -- неэффективное использование
кредита доверия к автору.

Вы не ответили на вопросы в моем предыдущем сообщении, т.е. не видите бессмысленность
выполняемых операций даже когда на них указано явно.
Списывать сейчас не сезон, но другое объяснение придумать трудно.

Вам надо отсортировать результаты по Z и пробовать только точки с близкими Z.

 Профиль  
                  
 
 Re: Вопрос по оптимазации скрипта
Сообщение03.08.2013, 19:27 


28/03/10
68
Sphinx Pinastri в сообщении #751554 писал(а):
Пожалуйста приведите программу, которая работает.
Поиск опечаток силами форума в том, что написано -- неэффективное использование
кредита доверия к автору.

Вы не ответили на вопросы в моем предыдущем сообщении, т.е. не видите бессмысленность
выполняемых операций даже когда на них указано явно.
Списывать сейчас не сезон, но другое объяснение придумать трудно.

Вам надо отсортировать результаты по Z и пробовать только точки с близкими Z.

Ok завтра приведу код. После улучшении показанных здесь переписал код на питон, и по ощущениям работает быстрее. За 3 часа нашел вариаграммы на 5 и 10 метров.

Сортировка по Z даст прирост в одном, но в тоже время по именам скважин будет бардак, не? Так как именно название скважин должно быть разным.

Может быть ход моих мыслей неверен, и есть какой нибудь алгоритм типо Эратосфена, который даст прирост не в 2 или 3 раза, а на порядок?

 Профиль  
                  
 
 Re: Вопрос по оптимазации скрипта
Сообщение03.08.2013, 22:46 
Аватара пользователя


20/10/12
308
Значений Z много, 500 и больше, сортировка позволит сразу отбросить
неподходящие точки. Это должно ускорить программу на 2 порядка.
Имен тоже много. Значит, вклад от совпадающих имен несущественный.

Далее, современные процессоры имеют 6-8 потоков комманд. Значит можно
пускать 8 процессов сразу. Если своих компьютеров не хватает, то стоит
попроситься к кому-нибудь из приятелей.

 Профиль  
                  
 
 Re: Вопрос по оптимазации скрипта
Сообщение04.08.2013, 06:11 


28/03/10
68
Вот код на питоне

from numpy import recfromcsv
GT=recfromcsv('GT.csv', delimiter = ',')
def variogram(name, h):
gamma=0.0
k=0
dist=float(h*h)
for i in range(1, 27274):
line=name[i][0]
z=name[i][3]
x=name[i][1]
y=name[i][2]
gt=name[i][4]

for j in range(i, 27275):
if (line!=name[j][0]) and ((z-name[j][3])<0.1) and (((x-name[j][1])*(x-name[j][1])+(y-name[j][2])*(y-name[j][2])+(z-name[j][3])*(z-name[j][3]))<=dist):
gamma=gamma+(gt-name[j][4])*(gt-name[j][4])
k+=1
return gamma/(2*k)
a=[]
for i in range(5, 101, 5):
a.append(variogram(GT, i))
print a

 Профиль  
                  
 
 Re: Вопрос по оптимазации скрипта
Сообщение04.08.2013, 06:32 
Аватара пользователя


20/10/12
308
Программу поместите в блок code а то опять гадать надо что к чему относится.

За одно проверьте, не нужен ли модуль в
Код:
(z-name[j][3])<0.1

 Профиль  
                  
 
 Re: Вопрос по оптимазации скрипта
Сообщение04.08.2013, 12:11 


28/03/10
68
Sphinx Pinastri в сообщении #751657 писал(а):
Программу поместите в блок code а то опять гадать надо что к чему относится.

За одно проверьте, не нужен ли модуль в
Код:
(z-name[j][3])<0.1

про модуль очень хорошо подсказали, совсем забыл про это))
Код:
from numpy import recfromcsv
GT=recfromcsv('GT.csv', delimiter = ',')
def variogram(name, h):
     gamma=0.0
     k=0
     dist=float(h*h)
     for i in range(1, 27274):
          line=name[i][0]
          z=name[i][3]
          x=name[i][1]
          y=name[i][2]
          gt=name[i][4]

          for j in range(i, 27275):
               if (line!=name[j][0]) and ((z-name[j][3])<0.1) and (((x-name[j][1])*(x-name[j][1])+(y-name[j][2])*(y-name[j][2])+(z-name[j][3])*(z-name[j][3]))<=dist):
                   gamma=gamma+(gt-name[j][4])*(gt-name[j][4])
                   k+=1
     return gamma/(2*k)
a=[]
for i in range(5, 101, 5):
     a.append(variogram(GT, i))
     print a

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 23 ]  На страницу 1, 2  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group