Besoin d'aide ! Je ne peux pas résoudre le problème, je me heurte à des limitations matérielles. - page 15

 

J'ai enfin trouvé ce qui est nécessaire, j'espère que cette version est finale.

Comme indiqué Tout est assez simple à décomposer et à paralléliser, les principales étapes :

1. a. Il serait très utile de savoir où se trouvent le début et la fin de chaque séquence (c'est pour cela que j'ai suggéré la dernière fois d'écrire leurs tailles dans un fichier séparé).

б. Vous pouvez les analyser vous-même, mais dans ce cas, vous devrez revenir au moment de lire la partie suivante du fichier sur le disque pour lire la séquence tronquée précédente.

Ensuite, je vais considérer la variante 1.a. Probablement, elle n'est pas optimale, mais je la préfère.

2. Connaissant la taille des séquences et la taille de la mémoire pour une partie du fichier (500 mb), nous pouvons calculer la taille de la partie du fichier que nous devons télécharger.

3. En parallèle, nous calculons les coefficients pour les séquences, puisque nous connaissons le début et la fin de chaque séquence.

4. Le début et la fin de chaque séquence peuvent être stockés dans la file d'attente multithread (remplie lors du calcul de l'étape 2).

5. Résultat du calcul - structure (tableau de la structure où le temps et le coefficient + le numéro de séquence))

6. Lorsque la moitié de la taille initiale de la mémoire allouée (250 mb) est traitée, le processus de réécriture est lancé avec la formation de la deuxième file d'attente avec le début et la fin

7. Après avoir atteint la fin de la première ligne, nous lisons la deuxième ; après avoir atteint la fin de la deuxième ligne, nous lisons la première.

8. Vous pouvez simultanément calculer les coefficients et lire le fichier.

9. Mais chaque résultat du calcul des coefficients doit être stocké, et il est préférable de les fusionner en une seule fois dans la réponse :

Nous devons écrire des fonctions de fusion : deux séquences de coefficients en un sousrésultat, deux sousrésultats en un sousrésultat légèrement complet.

10. Le processus de fusion peut également être effectué en parallèle.

11. A quand le résultat ? Lorsque les tailles des séquences lues dans le fichier complémentaire sont terminées, deux piles deviennent vides, puis le calcul des coefficients est terminé,

ensuite, nous devons attendre la fin du processus de fusion des sous-résultats (cela peut également être fait via une file d'attente sécurisée).

et enfin fusionner les sous-résultats des différents fils - résultat.


Voici une variante avec la charge maximale de tous les possibles, peut-être quelque chose de mieux - je serai heureux.

J'ai besoin de fonctions :

former une séquence de coefficients à partir d'une séquence d'entrée

fusion de deux séquences de coefficients en un seul sous-résultat (perte de précision possible ici)

fusion de deux sous-résultats en un seul sous-résultat légèrement complet (perte de précision possible ici)

 
komposter:

Je pense qu'il est possible d'inventer un mécanisme de chargement partiel astucieux, mais il faut l'inventer.

Par exemple, lors de la première lecture, trouvez pour chaque passe la dernière transaction clôturée avant la date de début, revenez en arrière et lisez X transactions précédentes, retenez le point du fichier où cette transaction se termine.

Après cela, trouvez la première transaction dans les résultats, puis travaillez uniquement avec des données fraîches : lisez le fichier depuis le point souhaité jusqu'à la nouvelle date réelle, et à chaque fois déplacez les transactions dans le tableau (obtenez un tableau de taille fixe - X éléments).

Cela résoudra le problème des lectures multiples (nous n'en avons tout simplement pas besoin) et de la mémoire (seulement si nous pouvons placer X millions de transactions).

Oui, c'est ce que l'algorithme fera.

  1. Redimensionner tous les tableaux d'offres à X éléments.
  2. Set SeekDate = StartDate.
  3. Ouvrir le fichier, commencer à lire, en remplissant séquentiellement le tableau des donnes de la première passe.
  4. Si les transactions, correspondant au passage, sont terminées (pas assez de transactions X), définissez la valeur du critère = N/A et passez au passage suivant.
  5. Si vous atteignez la transaction # (X+1), repoussez toutes les transactions précédentes (#1 est écarté, #2 devient #1, #X+1 devient #X).
  6. Si vous atteignez une transaction, dont l'heure d'ouverture >= la date de recherche (elle n'est pas ajoutée au tableau) :
    • Calculer la valeur de critère pour les transactions précédemment ajoutées #1 - #X
    • mémoriser la valeur du critère
    • mémoriser la position du pointeur de fichier avant la transaction
    • Passez à la séquence suivante
  7. Si la dernière séquence a été traitée :
    • Parcourir le tableau des séquences et trouver la meilleure valeur de critère
    • Aller à la position dans le fichier où se trouve la dernière transaction de la meilleure séquence.
    • Lire une transaction du fichier, l'ajouter au tableau (les transactions précédentes sont décalées).
    • Se souvenir de la position du pointeur de fichier
    • Écrire la transaction dans le fichier de résultat
    • Set SequentialDate = Heure de clôture de la transaction + 1
    • Nous continuons à boucler les séquences, à la seule condition que les tableaux soient déjà remplis, et que la lecture continue à partir du point mémorisé.

Si nous parvenons à allouer de la mémoire pour X millions de transactions(la taille de la structure est connue à l'avance), alors nous pourrons lire le fichier une fois.

Si ce n'est pas le cas, nous devons ajouter la lecture des X dernières transactions à chaque retour au pointeur Remembered. Le fichier sera alors lu plusieurs fois mais toujours de manière économique.

La structure de la séquence sera fixe : Nos, Trades[X], Critère, Position FilePointer. Il n'y a rien d'inutile.

Il faut encore coder =)

 

Quel est le résultat le plus souhaitable :

dll ou utiliser encore mql pour calculer ?

 

Oui, sous cette forme, la tâche est parallèle - chaque fois quele SeekDate change,vous pouvez exécuter une recherche simultanée du meilleur critère sur différentes parties de l'ensemble de séquences. Par exemple, nous les divisons en 20 parties et confions la tâche à 20 conseillers experts. Et ils doivent lire le dossier, trouver l'accord, et ne renvoyer que la meilleure séquence (№№, Critère et position du dossier).

Merci beaucoup à tous !

 
ALXIMIKS:

Quel est le résultat le plus souhaitable :

dll ou encore mql à calculer ?

Un meilleur mql, bien sûr. Et il est inutile d'écrire une dll, vous pouvez paralléliser dans MT également.
 

Je n'ai pas utilisé mql depuis six mois, je suis peut-être un peu bête, clarifiez si je me trompe :

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

Prévoyez-vous de faire une lecture séparée du disque pour chaque passage ? 10^6 fois lu à partir du disque ?

Ne peut-il pas y avoir un problème à lire individuellement au lieu de lire tout un morceau d'un coup ? Ou est-ce que tout est implémenté au plus haut niveau ici, avec une mise en mémoire tampon solide à souhait ?

Si nous atteignons une transaction dont l'heure d'ouverture est >= SeekDate (elle n'est pas ajoutée au tableau):

  • Set SeekingDate = Heure de clôture de l'affaire + 1
  • Nous continuons à boucler les séquences, avec la seule réserve que les tableaux ont déjà été remplis, et la lecture continue à partir du point stocké.

Je ne vois pas où la mémoire est libérée, elle continue de s'accumuler.

  • Passez en revue l'ensemble des séquences et trouvez la meilleure valeur de critère.

Pourquoi garder tout le tableau pour un seul Criterion ? Vous pouvez simplement les comparer lors du calcul d'un nouveau critère et conserver celui qui convient.

Si vous voulez trouver les 10 meilleurs critères, il est préférable de créer un tableau de 10 critères, de le remplir de valeurs, de le trier, puis d'insérer le critère suivant en utilisant la recherche binaire.

 
ALXIMIKS:

Prévoyez-vous d'effectuer une lecture séparée du disque pour chaque passage ? Lire 10^6 fois à partir du disque ?

Nous devrons de toute façon lire l'ensemble du fichier. Nous ne pouvons pas tout faire d'un coup (du début à la fin), nous devrons donc lire par morceaux (mais nous finirons quand même par avoir le fichier entier).

ALXIMIKS:

N'y a-t-il pas un problème à lire un morceau à la fois au lieu de lire tout le morceau d'un coup ? Ou est-ce que tout est implémenté au plus haut niveau ici, avec une mise en mémoire tampon solide à souhait ?

Un morceau est lu. La taille du morceau est déterminée par le nombre de transactions avant la date de recherche, qui se trouvaient dans une séquence particulière.

ALXIMIKS:

Je ne vois pas où la mémoire est libérée, elle continue de s'accumuler.

La mémoire est allouée une fois pour un tableau de structures de séquences.

La structure de la séquence comprend : le numéro, le tableau des structures de toutes les transactions de la séquence [X], la valeur du critère, la position du pointeur de fichier.

L'étape suivante consiste simplement à remplir les éléments de la structure (y compris les tableaux d'affaires). Les transactions du tableau sont décalées, de sorte qu'il n'y a toujours que X transactions de chaque séquence en mémoire.

ALXIMIKS:

Si vous voulez trouver les 10 meilleurs critères, il est préférable de créer un tableau de 10 critères, de le remplir de valeurs, de le trier, puis d'insérer le critère suivant en utilisant la recherche binaire.

Y compris pour la mise en parallèle.

Mais l'élimination d'un double d'une structure qui contient un tableau de structures de transactions ne fait pas de différence dans le cadre de la tâche.

 

Partager les résultats de mes recherches.

Le fichier cache binaire de 7529 MB se lit :

  • Depuis le disque dur : en 212,3 sec (35,46 Mo/sec)
  • Depuis le disque RAM : en 88,1 sec (85,46 MB/sec)
Il est difficile de qualifier la différence de cosmique, bien que j'aie le disque dur le plus courant (bien que la mémoire ne soit pas rapide non plus).

Conclusion : l'accélération de la lecture d'un gros fichier en utilisant le disque RAM est d'environ 2,5 fois.

 

Si le fichier était trié par heure des transactions non pas au sein des séquences, mais globalement (par toutes les séquences), alors l'algorithme suivant serait possible :

- Calculer le critère pour un métier, le considérer comme un candidat

- Nous calculons les critères pour les affaires qui commencent à l'intérieur de cette affaire, si nous obtenons le meilleur, nous changeons le candidat, si nous ne l'obtenons pas, nous considérons le candidat sélectionné et nous commençons un nouveau cycle à partir de la date de sa clôture.

Nous pouvons également trier par heure de fermeture - dans ce cas, nous commençons par la fin.

Il est clair que pour le calcul d'un critère, le fichier doit contenir un numéro de séquence pour chaque transaction.

Le re-tri d'un tel fichier n'est probablement pas une chose amusante non plus, nous pouvons essayer de l'écrire "correctement" en une fois. Il ne s'agit pas de générer des séquences entières une par une, mais de générer une transaction pour chaque séquence et d'utiliser un certain cache avec intelligence lors de l'écriture. Pour certains algorithmes de génération, bien sûr, cela peut être inacceptable.

 
Candid:

Si le fichier était trié par heure des transactions non pas au sein des séquences, mais globalement (par toutes les séquences), alors un tel algorithme serait possible :

- Calculez le critère de l'opération, considérez-la comme un candidat.

Supposons que j'enregistre un tel fichier (en convertissant simplement le fichier actuel, même si cela prend 15 heures de temps informatique).

Mais alors - sur le premier point - il y a un hic. Comment calculer le critère sur les X dernières transactions de la séquence, en ayant un tel fichier ?

Là encore, le critère ne peut être calculé une fois, ses paramètres peuvent changer.

Raison: