yardıma ihtiyacım var! Görev çözülmedi, demirin sınırlamalarıyla karşılaşıyorum - sayfa 15

 

Sonunda neye ihtiyacım olduğunu anladım, umarım bu versiyon nihaidir.

Söylendiği gibi, Her şey oldukça basit bir şekilde bölünmüş ve paralelleştirilmiştir, ana aşamalar şunlardır:

1 A. Her dizinin başlangıcının ve bitişinin nerede olduğunu bilmek çok faydalı olacaktır (bu yüzden geçen sefer boyutlarını ayrı bir dosyaya yazmayı önermiştim)

b. Kendinizi ayrıştırabilirsiniz, ancak önceki kesilmiş diziyi okumak için dosyanın bir sonraki bölümünü diskten okurken geri dönmeniz gerekir.

Ayrıca 1.a seçeneğini değerlendireceğim. İdeal olmayabilir, ama ben daha çok seviyorum.

2. Dizilerin boyutunu ve dosyanın bir bölümü için bellek boyutunu (500 mb) bilerek, dosyanın indirilmesi gereken bölümünün boyutunu hesaplayabiliriz.

3. Paralel olarak, her dizinin başlangıcını ve sonunu bildiğimiz için dizilerin katsayılarını hesaplarız.

4. Her dizinin başlangıcı ve sonu çok iş parçacıklı bir kuyrukta saklanabilir (2. nokta hesaplanırken doldurulur)

5. Hesaplama sonucu - yapı (zaman ve katsayı + sıra numarasının bulunduğu yapıdan dizi)

6. Tahsis edilen hafızanın ilk boyutunun yarısı işlendiğinde (250 MB), başlangıçları ve bitişleri olan ikinci kuyruğun oluşturulması ile ekleme işlemi başlatılır.

7. İlk sıranın sonuna kadar saydıktan sonra - ikinciden okuyoruz; saniyenin sonuna kadar saydıktan sonra - ilk turdan itibaren okuduk.

8. Paralel katsayıların hesaplanmasını ve bir dosyadan okumasını düzenleyebilirsiniz.

9. Ancak katsayıları hesaplamanın her sonucu saklanmalıdır ve burası, yanıt olarak bunları hemen birleştirmek daha iyidir:

bir birleştirme işlevi yazmanız gerekir: iki katsayı dizisi bir alt sonuca, iki alt sonuç tek bir tam alt sonuca

10. Birleştirme işlemi paralel olarak da yapılabilir.

11. Sonuç ne zaman olacak? Ek dosyadan okunan dizilerin boyutları bittiğinde, iki yığın boşalacaktır, ardından katsayıların hesaplanması sona erecektir,

daha sonra alt sonuçları birleştirme işleminin sonuna kadar beklemeniz gerekir (aynı zamanda iş parçacığı için güvenli bir kuyruk da kullanabilirsiniz)

ve son olarak farklı akışların alt sonuçlarını birleştirin - sonuç.


İşte mümkün olan her şeyin maksimum yüküyle böyle bir seçenek, belki bir şey daha iyidir - Memnun olacağım.

işlevlere ihtiyaç duyar:

giriş dizisinden bir katsayı dizisi oluşturma

iki katsayı dizisini tek bir alt sonuç halinde birleştirmek (burada olası hassasiyet kaybı)

iki alt sonucun biraz tam bir alt sonuç halinde birleştirilmesi (burada olası hassasiyet kaybı)

 
komposter :

Zor bir kısmi yükleme mekanizması icat etmenin mümkün olduğunu düşünüyorum, ancak icat edilmesi gerekiyor.

Örneğin, ilk okuma sırasında, her geçiş için Başlangıç Tarihinden önce kapatılan son anlaşmayı bulun, geri dönün ve X önceki anlaşmayı okuyun, bu anlaşmanın bittiği dosya noktasını hatırlayın.

Bundan sonra, sonuçlara dahil edilen ilk anlaşmayı bulun ve ardından yalnızca yeni verilerle çalışın: dosyayı istediğiniz noktadan yeni geçerli tarihe kadar okuyun ve dizideki anlaşmaları her kaydırdığınızda (sabit bir dizi boyutu elde edersiniz) - X öğeleri).

Bu, hem çoklu okuma problemini (sadece gerekli değildir) hem de hafıza problemini (sadece X milyon işlem sığdırabilirsek) çözecektir.

Evet, algoritma bu.

  1. Tüm anlaşma dizilerini X öğeye kadar yeniden boyutlandırın.
  2. AramaTarihi = BaşlangıçTarihi olarak ayarlayın.
  3. Dosyayı açarız, okumaya başlarız, sırayla ilk geçişin anlaşma dizisini doldururuz.
  4. Geçişe karşılık gelen işlemler sona erdiyse (X işlem toplanmadı), kriter değerini = H/A olarak ayarlayın ve sonraki geçişe geçin.
  5. # (X+1) anlaşmasına ulaşırsak, önceki tüm anlaşmaları geri kaydırırız (1 numara atılır, #2 #1 olur, #X+1 #X olur).
  6. Açılış zamanı >= SearchedDate (diziye eklenmemiş) olan bir anlaşmaya varırsak:
    • Önceden eklenen 1 Numaralı - X Numaralı işlemler için Kriter değerini hesaplayın
    • Kriterin değerini hatırlamak
    • Bu işlemden önce dosya işaretçisinin konumunu hatırlıyoruz
    • Sonraki sıraya geç
  7. Son dizi işlenirse:
    • Dizi dizisinden geçiyoruz ve Kriter'in en iyi değerini buluyoruz.
    • En iyi dizinin son fırsatının bulunduğu dosyada kayıtlı konuma gidin
    • Dosyadan anlaşmayı okuyun, diziye ekleyin (önceki anlaşmaları kaydırıyoruz)
    • Dosya işaretçisinin konumunu hatırlama
    • Anlaşmayı sonuç dosyasına yazın
    • HedefTarihi Ayarla = İşlem Kapanış Saati + 1
    • Dizilerin zaten dolu olduğu ve okumanın hafızaya alınan noktadan devam ettiğine dair tek uyarı ile dizileri numaralandırmaya devam ediyoruz.

X milyon işlem için bellek ayırmak mümkünse ( yapının boyutu önceden bilinir), o zaman dosyayı bir kez okumak mümkün olacaktır.

Değilse, Hatırlanan İşaretçiye her döndüğünüzde son X işlemin bir okumasını eklemeniz gerekir. Ardından dosya birçok kez okunacak, ancak yine de idareli bir şekilde okunacaktır.

Dizinin yapısı sabittir: ##, İşlemler[X], Criterion, PositionFilePointer. Ekstra bir şey yok.

Kodlamak için kalır =)

 

Ve daha arzu edilen sonuç nedir:

dll veya hala mql ile hesaplamak?

 

Evet, bu formda görev paralelleştirilir - Arama Tarihindeki her değişiklikle, dizi setinin farklı bölümlerinde en iyi Kriter için eşzamanlı bir arama başlatabilirsiniz. Örneğin, bunları 20 parçaya bölün ve görevleri 20 danışmana dağıtın. Ve dosyayı okumalarına, bir anlaşma bulmalarına ve yalnızca en iyi diziyi (##, Kriterler ve dosya konumu) geri göndermelerine izin verin.

Herkese çok teşekkürler!

 
ALXIMIKS :

Ve daha arzu edilen sonuç nedir:

dll veya hala mql ile hesaplamak?

Tabii ki daha iyi mikro. Evet ve dll yazmanın bir anlamı yok, MT'de paralel hale getirebilirsiniz.
 

Yarım yıldır mql ile birlikte değilim, biraz aptal olabilirim, yanılıyor muyum kontrol edin:

Открываем файл, начинаем читать, последовательно заполняя массив сделок первого прохода  

Her geçiş için ayrı ayrı diskten okumayı planlıyor musunuz? Diskten 10^6 kez okunsun mu?

Parçanın tamamını bir kerede okumak yerine tek tek okumakta bir sakınca olamaz mı? Yoksa her şey yedekte katı tamponlama ile en üst düzeyde mi uygulanıyor?

Açılış zamanı >= SearchedDate (diziye eklenmemiş) olan bir anlaşmaya varırsak:

  • HedefTarihi Ayarla = İşlem Kapanış Saati + 1
  • Dizilerin zaten dolu olduğu ve okumanın hafızaya alınan noktadan devam ettiğine dair tek uyarı ile dizileri numaralandırmaya devam ediyoruz.

Hafızanın nerede serbest kaldığını göremiyorum, birikmeye ve birikmeye devam ediyor.

  • Dizi dizisinden geçiyoruz ve Kriter'in en iyi değerini buluyoruz.

neden bütün bir diziyi tek bir ölçüt için tutalım? Ayrıca yeni bir kriter hesaplarken basitçe karşılaştırabilir ve uygun olanı bırakabilirsiniz.

En iyi 10 kriteri bulmak istiyorsanız, o zaman 10 kriterden oluşan bir dizi yapmak, ardından onu değerlerle doldurmak, sıralamak ve ikili arama ile aşağıdaki kriterleri eklemek daha uygundur.

 
ALXIMIKS :

Her geçiş için ayrı ayrı diskten okumayı planlıyor musunuz? Diskten 10^6 kez okunsun mu?

Yine de her şeyi okumak zorundasın. Tek seferde çalışmıyor (baştan sona), bu yüzden parçalar halinde okuyacağız (ama yine de sonunda, tüm dosya).

ALXIMIKS :

Parçanın tamamını bir kerede okumak yerine tek tek okumakta bir sakınca olamaz mı? Yoksa her şey yedekte sağlam tamponlama ile en üst düzeyde mi uygulanıyor?

Bir parça okunuyor. Yığın boyutu, belirli bir sıradaki Arama Tarihinden önceki anlaşmaların sayısına göre belirlenir.

ALXIMIKS :

Hafızanın nerede serbest kaldığını göremiyorum, birikmeye ve birikmeye devam ediyor.

Bellek, bir dizi dizi yapısı için bir kez tahsis edilir.

Dizinin yapısı şunları içerir: #, [X] dizisindeki tüm anlaşmaların yapı dizisi, Ölçüt Değeri, Dosya İşaretçisinin Konumu.

Sonraki adım, yalnızca yapının öğelerini doldurmaktır (anlaşma dizileri dahil). Dizideki fırsatlar kaydırılır, bu nedenle bellekteki her dizide her zaman yalnızca X anlaşma vardır.

ALXIMIKS :

En iyi 10 kriteri bulmak istiyorsanız, o zaman 10 kriterden oluşan bir dizi yapmak, ardından onu değerlerle doldurmak, sıralamak ve ikili arama ile aşağıdaki kriterleri eklemek daha uygundur.

Paralelleştirme dahil.

Ancak görev çerçevesinde, bir dizi işlem yapılarının bulunduğu yapıdan bir çiftin çıkarılması bir fark yaratmaz.

 

Araştırma sonuçlarımı paylaşıyorum.

7529 MB'lık bir ikili önbellek dosyası şunları okur:

  • sabit sürücüden: 212,3 saniyede (35,46 MB/sn)
  • RAM diskten: 88.1 saniyede (85.46 MB/sn)
Sabit diskimin en yaygın olmasına rağmen (bellek yüksek hızlı olmasa da) farkı kozmik olarak adlandırmak zor.

Sonuç: RAM disk kullanarak büyük bir dosyayı okumadaki hızlanma yaklaşık 2,5 kattır.

 

Dosya, ticaret zamanına göre diziler içinde değil de global olarak (tüm diziler üzerinden) sıralansaydı, aşağıdaki algoritma mümkün olurdu:

- Anlaşmanın kriterini hesaplıyoruz, aday olarak kabul ediyoruz

- Bu işlem içinde başlayan işlemler için kriterleri hesaplıyoruz, en iyisi gelirse adayı değiştiriyoruz, değilse seçilen adayı dikkate alıyoruz, kapanış tarihinden itibaren yeni bir döngüye başlıyoruz.

Kapanış saatine göre de sıralayabilirsiniz, sonra sondan hareket ederiz.

Kriterin hesaplanması için dosyanın her işlem için sıra numarasını içermesi gerektiği açıktır.

Böyle bir dosyayı yeniden sıralamak da muhtemelen eğlenceli değildir, hemen "olması gerektiği gibi" yazmayı deneyebilirsiniz. Yani, sırayla tüm dizileri oluşturmak için değil, her dizi için sırayla bir ticaret oluşturmak ve yazarken zeka ile küçük bir önbellek kullanmak. Bazı nesil algoritmalar için bu elbette kabul edilemez olabilir.

 
Candid :

Dosya, ticaret zamanına göre diziler içinde değil de global olarak (tüm diziler üzerinden) sıralansaydı, aşağıdaki algoritma mümkün olurdu:

- İşlem için kriteri hesaplıyoruz, aday olarak kabul ediyoruz

Diyelim ki böyle bir dosya yazdım (15 saat bilgisayar zamanını alsa bile sadece mevcut olanı dönüştürün).

Ama tam orada - ilk noktada - bir fiş. Böyle bir dosyaya sahip olan dizinin son X anlaşmaları için kriter nasıl hesaplanır?

Tekrar ediyorum, Kriter bir kez hesaplanamaz, parametreleri değişebilir.