Je veux créer et manipuler de grandes tableaux de (4 octets) en mémoire en mémoire. Par grand, je veux dire sur l'ordre de centaines de millions. Chaque cellule de la matrice agira comme un compteur pour une position sur un chromosome. Tout ce dont j'ai besoin, c'est que cela s'adapte à la mémoire et d'avoir un accès rapide (O (1)) aux éléments. La chose que je compte n'est pas une caractéristique clairsemée, je ne peux donc pas utiliser un tableau rare.
Je ne peux pas faire cela avec une liste de perl régulière, car Perl (au moins sur ma machine) utilise 64 octets par élément, de sorte que les génomes de la plupart des organismes que je travaille sont trop gros. J'ai essayé de stocker les données sur disque via SQLite et hachage, et bien qu'ils fonctionnent, sont très lents, en particulier sur des lecteurs ordinaires. (Cela fonctionne raisonnablement d'accord lorsque je fonctionne sur un raid à 4 lits 0). P>
Je pensais utiliser des tableaux PDL, B / C PDL stocke ses tableaux tout comme c, en utilisant seulement 4 octets par élément. Cependant, j'ai constaté que la vitesse de mise à jour lente d'excrétiser par rapport aux listes Perl: p> retourne: p> Est-ce que quelqu'un Savoir comment augmenter les performances définies PDL () ou savoir un module différent pouvant accomplir cela? P> P>
7 Réponses :
PDL gagne lorsque les opérations peuvent être filetées, apparemment, elle n'est pas optimisée pour un accès aléatoire et une affectation. Peut-être que quelqu'un avec plus de connaissances PDL pourrait aider. P>
Ce n'est pas l'accès aléatoire mais le temps de démarrage pour initialiser les structures de données PDL. Selon le calcul impliqué, le PDL nécessite de 100 à 1 000 éléments à traiter avant de percer même en performance avec des opérations de Perl autochtones. Avec son soutien à la boucle implicite, une ligne de code PDL peut remplacer plusieurs boucles de scalaire ou de liste imbriquées dans des perl ordinaires.
Vous seriez le meilleur à savoir, merci pour le commentaire. Certainement, il y a de meilleures réponses postées dans cette question maintenant que la mienne. :-)
Je ne peux pas dire quel type de performance vous obtiendrez, mais je recommande d'utiliser la fonction VEC code>, documentée ici , pour diviser une chaîne en champs de bits. J'ai expérimenté et j'ai constaté que mon Perl tolérera une chaîne jusqu'à
500_000_000 code> caractères longtemps. Ce qui correspond à 125 000 000 valeurs 32 bits.
Rate pdl vec perl
pdl 472429/s -- -76% -85%
vec 1993101/s 322% -- -37%
perl 3157570/s 568% 58% --
Emballé :: Array sur CPAN pourrait vous aider. p>
Emballé :: Array fournit une classe d'entière compensée signée. Les tableaux construits à l'aide d'emballés :: Array ne peuvent contenir que des entiers signés qui correspondent à vos entiers natifs à la plate-forme, mais ne prenez que autant de mémoire que nécessaire pour contenir ces entiers. Ainsi, pour les systèmes 32 bits, plutôt que de prendre environ 20 octets par entrée de réseau, ils ne prennent que 4. P> blockQuote>
Oui j'ai regardé ce module, ainsi que Cravate :: Array :: Pack Code>,
Cravate :: Array :: Emballé Code>,
Cravate :: Vecarray Code> et
Cravate :: Array :: Packedc Code>. Malheureusement, le Perl
Cravate Code> API est très lent et le plus rapide (
Array :: Array :: Emballé Code>) reste dix fois plus lent que les matrices natives.
La commande PDL que vous voulez est PDL est conçu pour ce que j'appelle des opérations "vectorisées". Par rapport aux opérations C, les opérations de Perl sont assez lentes. Vous souhaitez donc conserver le nombre d'invocations de méthode PDL au minimum et que chaque invocation ait beaucoup de travail. Par exemple, ce benchmark vous permet de spécifier le nombre de mises à jour à effectuer en une seule go (en tant que paramètre de ligne de commande). Le côté Perl doit boucler, mais le côté PDL ne fonctionne que cinq appels de fonction: p> Quand je l'exécute avec un argument de 1, je reçois encore pire des performances que Lorsque vous utilisez C'est beaucoup de terrain à maquillage! Mais tenez là-bas. Si nous faisons 100 itérations par tour, nous obtenons une amélioration: p> et avec 10 000 mises à jour par tour, PDL surperforms Perl par un facteur de quatre: p> indadd code>. (Merci à Chris Marshall, PDL Pumpking, pour le pointant sur moi ailleurs .)
définir code>, ce que je m'attendais à: p>
use PDL;
use Benchmark qw/cmpthese/;
my $updates_per_round = shift || 1;
my $N = 1_000_000;
my @perl = (0 .. $N - 1);
my $pdl = zeroes $N;
my $inline = pack "d*", @perl;
my $max_PDL_per_round = 5_000;
use Inline 'C';
cmpthese(-1,{
perl => sub{
$perl[int(rand($N))]++ for (1..$updates_per_round);
},
pdl => sub{
my $to_update = long(random($updates_per_round) * $N);
indadd(1,$to_update,$pdl);
},
inline => sub{
do_inline($inline, $updates_per_round, $N);
},
});
__END__
__C__
void do_inline(char * packed_data, int N_updates, int N_data) {
double * actual_data = (double *) packed_data;
int i;
for (i = 0; i < N_updates; i++) {
int index = rand() % N_data;
actual_data[index]++;
}
}
pdl :: Set () code> et
pdl :: get (get () code> est destiné à une aide d'apprentissage que toute autre chose. Ils constituent le moyen pessimal d'accéder aux variables PDL. Vous seriez bien mieux d'utiliser certaines des routines d'accès en vrac intégrées. Le constructeur PDL accepte lui-même les listes PERL:
$pdl->bswap4;
$dr = $pdl->get_dataref;
vec($$dr,int(rand($N)),32)++;
$pdl->upd_data;
$pdl->bswap4;
depuis que vous utilisiez des entiers, ce qui devrait être ok pour une utilisation
avec des chromosomes, essayez ceci et le put que j'ai eu à partir de c'était ... p> qui montre une grande différence de performance
de quand j'ai essayé d'abord ce code sans
Ajouter dans mes 2 cents, j'ai reçu p>
ma réponse ci-dessus peut être sans valeur ... Cela pourrait aider.
$PDL::BIGPDL=1;
Avez-vous regardé les modules de Bioinformatics Perl?