32 votes

Existe-t-il une solution de contournement à la limite en ligne C 28 heures?

Je suis en train de travailler sur l'optimisation d'un programme de simulation de la physique à l'aide de Red Gate Performance Profiler. Une partie du code portant sur la détection de collision avait autour de 52 de la suite de petits chèques, traitant avec les cellules de 26 directions en 3 dimensions, en vertu de deux cas.

CollisionPrimitiveList cell = innerGrid[cellIndex + 1];
if (cell.Count > 0)
    contactsMade += collideWithCell(obj, cell, data, ref attemptedContacts);

cell = innerGrid[cellIndex + grid.XExtent];
if (cell.Count > 0)
    contactsMade += collideWithCell(obj, cell, data, ref attemptedContacts);

cell = innerGrid[cellIndex + grid.XzLayerSize];
if (cell.Count > 0)
    contactsMade += collideWithCell(obj, cell, data, ref attemptedContacts);

Comme très serrée de la boucle du programme, tout cela devait être dans la même méthode, mais j'ai trouvé que, tout à coup, après j'ai eu étendue de la zone à partir de deux dimensions à trois dimensions (à la hausse le comte de 52 chèques à partir de 16 ans), du coup cellule.Le comte n'était plus inline, même si c'est un simple de lecture. public int Count { get { return count; } } Cela a provoqué un énorme gain de performance, et il m'a fallu un temps considérable pour trouver que, lorsque la cellule.Le comte est apparu dans la méthode de 28 fois ou moins, il a été incorporé à chaque fois, mais une fois la cellule.Le comte est apparu dans la méthode de 29 fois ou plus, il n'a pas été intégrées en une seule fois (même si la grande majorité des appels ont été de pire des cas, certaines parties du code qui ont été rarement exécutée).

Donc, pour revenir à ma question, quelqu'un at-il une idée pour contourner cette limite? Je pense que la solution de facilité est juste pour faire le décompte de champ interne et pas en privé, mais je voudrais une meilleure solution que celle-ci, ou au moins juste une meilleure compréhension de la situation. Je souhaite que ce genre de chose aurait été mentionné sur Microsoft d'Écriture de Haute Performance des Applications Gérées page http://msdn.microsoft.com/en-us/library/ms973858.aspx mais malheureusement il n'est pas (peut-être parce que de façon arbitraire le 28, le nombre maximum est?)

Je suis à l'aide .NET 4.0.

EDIT: Il semble que j'ai mal interprété mon petit test. J'ai trouvé que le non-inline n'est pas causée par les méthodes elles-mêmes d'être appelé quelque 28+ les temps, mais parce que la méthode qu'ils devraient être incorporé est "trop long" par certains standard. Cette confond encore moi, parce que je ne vois pas comment un simple getter peut être rationnellement pas inline (et de la performance est nettement meilleure avec eux inline comme mon profiler clairement montre moi), mais apparemment, la CLI compilateur JIT refusant de inline quoi que ce soit simplement parce que la méthode est déjà importante (jouer avec de légères variations m'a montré que cette limite est la taille du code (à partir de idasm) de 1500, au-dessus duquel aucune inline est fait, même dans le cas de mon getters, qui certains tests ont montré que de ne pas ajouter de code supplémentaire de frais généraux pour être incorporé).

Je vous remercie.

4voto

Gabe Points 49718

Je n'ai pas testé, mais il semble comme une solution possible est d'avoir plusieurs propriétés que tous reviennent à la même chose. Éventuellement, vous pourriez obtenir 28 inlines par propriété.

Notez que le nombre de fois qu'une méthode est incorporé plus susceptibles dépend de la taille de code natif pour cette méthode (Voir http://blogs.msdn.com/b/vancem/archive/2008/08/19/to-inline-or-not-to-inline-that-is-the-question.aspx), le nombre 28 est spécifique à une seule propriété. Une propriété simple susceptibles d'avoir incorporé plus de fois qu'une méthode plus complexe.

1voto

Neil Moss Points 3581

Tout de suite, cela n'explique pas pourquoi 28 est le nombre magique, mais je suis curieux de savoir ce qui pourrait arriver si vous rassembler tous de votre candidat CollisionListPrimitive cas dans un tableau, et ensuite appeler votre "si nombre > 0" bloc à l'intérieur d'une boucle de la matrice?

Est la cellule.Le comte appel, puis faites inline nouveau?

par exemple

CollisionPrimitiveList[] cells = new CollisionPrimitiveList {
    innerGrid[cellIndex + 1],
    innerGrid[cellIndex + grid.XExtent],
    innerGrid[cellIndex + grid.XzLayerSize]
    // and all the rest
};

// Loop over cells - for demo only. Use for loop or LINQ'ify if faster
foreach (CollisionPrimitiveList cell in cells) 
{
    if (cell.Count > 0)
        contactsMade += collideWithCell(obj, cell, data, ref attemptedContacts);  
}

Je sais que la performance est la question, et vous aurez les frais généraux de la construction de la matrice et la boucle à travers elle, mais si la cellule.Le comte est en ligne encore une fois, les performances être encore mieux / assez bon dans l'ensemble?

0voto

Mehrdad Points 70493

J'imagine (bien que ce ne soit nullement positif) que cela pourrait avoir un rapport avec le problème d' enregistrement mentionné - il est possible que le CLR alloue une nouvelle variable pour chaque instruction if, et que celles-ci dépassent un total de 64 variables. Pensez-vous que cela pourrait être le cas?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X