stdray: (Default)
stdray ([personal profile] stdray) wrote2012-09-27 05:45 am

Многомерные массивы

Выбирает, видимо, себе язык под проект мой, можно сказать, знакомый. Набигает с нехитрой задачей: создать трехмерный массив определенного размера, а потом пробежаться по нему 20 раз, присваивая значения счетчика. Потрать 5 минут, говорит, сделай на F#, чтобы его показатели тоже были. Мне нетрудно - взял и написал не идиоматический код с мутабельностью и форами.
  1. open System  
  2. open Microsoft.FSharp.Collections  
  3.   
  4. let beforeAllocation = DateTime.Now  
  5. let yobaArray        = Array3D.zeroCreate 512 512 128  
  6. let afterAllocation  = DateTime.Now  
  7. let mutable i = 0  
  8. for n in 1..20 do   
  9.     for x in 0..511 do   
  10.     for y in 0..511 do   
  11.     for z in 0..127 do   
  12.         yobaArray.[x, y, z] <- i  
  13.         i <- i + 1  
  14. let afterLoop       = DateTime.Now  
  15. let totalLoopTime   = afterLoop - afterAllocation  
  16. let averageLoopTime = new TimeSpan(totalLoopTime.Ticks / 20L)  
  17. printfn "Allocation time: %A"   <| afterAllocation - beforeAllocation  
  18. printfn "Total loop time: %A"   <| totalLoopTime  
  19. printfn "Average loop time: %A" <| averageLoopTime   

Да и фиг бы с ними, явно речь идет про скорость аллокации и доступа. Для такой задачи, оно может и лучше даже. И выдает это чудо какое-то время
Allocation time: 00:00:00.0290017
Total loop time: 00:00:57.4592865
Average loop time: 00:00:02.8729643

и фиг его знает, нормальное оно или нет. Тут даже корявый подсчет через DateTime.Now роли не играет, большие чиcла же. Поглядели другие кусочки кода, результаты почитали. Хотя какой смысл сравнивать, если у всех машины разные и результаты в вакууме получаются. Питон попробовали покормить такой-то аллокацией таких-то массивов, наблюдая как он крашится, хотя списки списков списков нам создать таки удалось, а вот заполнения дождались с трудом. Нету никаких массивов в питоне кроме тех, что в нумпае лежат. Еще руби пытались заставить делать такое, только он массив выделил, а шевелился медленно-медленно, автор так и не дождался результатов и спать ушел. А я декомпильнул фишарповское приложение в додиез с вопросом "Array3d ты кто такой? дава"

На удивление мало собачек и циферок я разлядел. Ну а Array3d - это многомерный массив. Только я забыл, что он из себя представляет и как под него память аллоцирутеся. Точно помню, был момент, мол чем же [1][2] от [1,2] отличается. Но, видать, так не сильно нужно было. Потом я набросал небольшой тест для 3 видов трехмерных интовых массивов.

Можно посмотреть писанину: http://pastebin.com/mwqnm2re
Test allocate ragged array: 0,8430482 seconds
Test fill ragged array in xyz order: 11,9506836 seconds (repeated 20 avr 0,59753418 seconds)
Test allocate multidimension array: 0,0010001 seconds
Test fill multidimension in xyz order: 22,6692966 seconds (repeated 20 avr 1,13346483 seconds)
Test allocate flat array: 0,0900052 seconds
Test fill flat array in xyz order: 38,1171802 seconds (repeated 20 avr 1,90585901 seconds)
Test fill flat array in xzy order: 38,8362213 seconds (repeated 20 avr 1,941811065 seconds)

Там наверное ошибки есть, которых я не замечаю. Но суть должна быть ясна. Сначала протестировал массив массивов, потом многомерные эти, потом выделил плоскую лапшу и руками смапил на нее трехмерные координаты. Во-первых, как-то забываешь, что по массивам надо ползать в правильном направлении, иначе можно схлопотать какую-то жуткую потерю скорости на ровном месте. Во-вторых, чем этот многомерный массив занимается, я так и не понял. Он _медленнее_ массива массивов при доступе, хотя выделяется моментально, да. Но, блин, если уж массив создаем, значит с ним работать надо, иначе можно иммутабельными структурами обойтись. А плоская моя самоделка - совсем ни в какие ворота, хотя тоже непонятно почему. Вроде вот тебе указатель, вот тебе смещение... Хотя, конечно, мы не с няшной сишкой дело имеем, хотя и тут какой-то адов ансейф на указателях устраивать можно, но ну его нафиг, бе.

Кароче, как-то я потерялся за этот вечер. Устройства дотнетов не знаю. Надо доставать Рихтера, хотя читал уже. Досадно. Хотя, в любом случае, надо отметить, что clr с задачей справляется, как вообщем-то и jvm. А вот модные скрипто-игрушки совершенно не але, по крайней мере в лоб стандартными средствами языка. А ведь за всем этим гламурным кодом и рассуждениями за чистоту и функторы легко забываешь, что где-то внутри выделяется память, кешируется что-то и вообще все всё за тебя решают.

[identity profile] sassa-nf.livejournal.com 2012-09-27 07:20 am (UTC)(link)
x * SizeY * SizeZ + y * SizeZ + z => (x * SizeY + y) * SizeZ + z

[identity profile] stdray.livejournal.com 2012-09-27 08:43 am (UTC)(link)
Протестирую. Если верить thedeemon сэкономленное умножение должно быть ощутмо сказаться на этой задаче.