سؤال

يتم تشغيل التعليمات البرمجية التالية ببطء شديد على الرغم من أن كل شيء يبدو مقهدا.

from numpy import *
from scipy.sparse import *

n = 100000;
i = xrange(n); j = xrange(n);
data = ones(n);

A=csr_matrix((data,(i,j)));

x = A[i,j]

يبدو أن المشكلة هي أن عملية الفهرسة يتم تنفيذها كدالة بيثون، وتسهيل A[i,j] يؤدي إلى إخراج التنميط التالي

         500033 function calls in 8.718 CPU seconds

   Ordered by: internal time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
   100000    7.933    0.000    8.156    0.000 csr.py:265(_get_single_element)
        1    0.271    0.271    8.705    8.705 csr.py:177(__getitem__)
(...)

وهي وظيفة بيثون _get_single_element يطلق عليه 100000 مرة وهو غير فعال حقا. لماذا لا يتم تنفيذ هذا في نقي ج؟ هل يعرف أي شخص وسيلة للتحصيل هذا القيد، وتسريع الكود أعلاه؟ يجب أن أستخدم نوع مصفوفة متفرق مختلفة؟

هل كانت مفيدة؟

المحلول

يمكنك استخدام A.diagonal() لاسترداد القطرية بسرعة أكبر بكثير (0.0009 ثانية مقابل 3.8 ثانية على جهازي). ومع ذلك، إذا كنت ترغب في إجراء الفهرسة من النزهة، فهذا هو سؤال أكثر تعقيدا لأنك لا تستخدم شرائح بقدر قائمة من المؤشرات. يتم استدعاء وظيفة _get_single_element 100000 مرة لأنها تكرار فقط من خلال المحامي (I و J) التي مرت بها. سيكون شريحة [30: 60،10] أو شيء مشابه لذلك.

أيضا، أود استخدام csr_matrix(eye(n,n)) لجعل نفس المصفوفة التي قمت بها مع المحفوثة فقط للبساطة.

تحديث:

حسنا، نظرا لأن سؤالك هو حقا قادر على الوصول إلى الكثير من العناصر العشوائية بسرعة، سأجيب على أسئلتك بأفضل ما أستطيع.

  • لماذا لا يتم تنفيذ هذا في نقي ج؟

الجواب بسيط: لم يحصل أحد عليه. لا يزال هناك الكثير من العمل الذي يتعين القيام به في منطقة مصفوفة متفرق منطقة SCIPY من ما رأيته. جزء واحد يتم تنفيذه في C هو التحويلات بين تنسيقات مصفوفة متفرق مختلفة.

  • هل يعرف أي شخص وسيلة للتحصيل هذا القيد، وتسريع الكود أعلاه؟

يمكنك محاولة الغوص في الواقع في وحدات مصفوفة Sparse وتحاول تسريعها. فعلت ذلك وكنت قادرا على الحصول على الوقت إلى أقل من ثلث الأصلي عند محاولة الخروج من التعليمات البرمجية أعلاه للوصول العشوائي باستخدام مصفوفات CSR. اضطررت إلى الوصول مباشرة إلى _Single_Element مباشرة وأحلى الكود بشكل كبير للقيام بذلك بما في ذلك إخراج الشيكات المحددة.

ومع ذلك، فقد كان الأمر أسرع استخدام LIL_MATRIX (على الرغم من أن أبطأ لتهيئة المصفوفة)، ولكن كان علي القيام بالوصول إلى فهم قائمة لأن مصفوفات الليل ليست إعداد لنوع الفهرسة الذي تقوم به. باستخدام فهم قائمة ل CSR_MATRIX لا يزال يترك طريقة Lil Matrix طريقة قدما بالمناسبة. في نهاية المطاف، يكون Lil Matrix أسرع للوصول إلى عناصر عشوائية لأنه غير مضغوط.

يعمل استخدام LIL_MATRIX في شكله الأصلي في حوالي خمس وقت الرمز الذي أدخلته أعلاه. إذا قمت بإخراج بعض الشيكات المحددة والاتصال بطريقة Lil_matrix's _get1 () مباشرة، يمكنني إحضار الوقت إلى أسفل حوالي 7٪ من الوقت الأصلي. بالنسبة للوضوح، فهذا السرعة من 3.4-3.8 ثانية إلى حوالي 0.261 ثانية.

أخيرا، حاولت إجراء وظيفتي الخاصة التي تصل مباشرة إلى بيانات Lil Matrix وتجنب مكالمات الدالة المتكررة. كان الوقت لهذا هو حوالي 0.136 ثانية. لم يستفيد هذا من البيانات التي يتم فرزها والتي هي تحسين محتمل آخر (على وجه الخصوص إذا كنت ترغب في الوصول إلى الكثير من العناصر الموجودة على نفس الصفوف).

إذا كنت تريد أسرع من ذلك، فسيتعين عليك كتابة تطبيق Matrix Code Sprse الخاص بك على الأرجح.

  • يجب أن أستخدم نوع مصفوفة متفرق مختلفة؟

حسنا، أقترح أن تكون مصفوفة الليل إذا كانت نيتك هي الوصول إلى الكثير من العناصر، ولكن كل ذلك يعتمد على ما تحتاج إلى القيام به. هل تحتاج أيضا إلى ضرب المصفوفات على سبيل المثال؟ فقط تذكر أن التغيير بين المصفوفات يمكن أن يكون في بعض الأحيان في بعض الأحيان (في ظروف معينة) بسرعة كبيرة، لذلك لا تستبعد التغيير إلى تنسيق مصفوفة مختلف للقيام بعمليات مختلفة.

إذا كنت لا تحتاج إلى القيام بأي عمليات جبرية في مصفوفة، فربما يجب عليك فقط استخدام DefaultDict أو شيء مشابه. الخطر الذي يحتوي على DefaultDicts هو أنه كلما طلب عنصر أنه غير موجود في DICT، فإنه يضع هذا البند إلى الافتراضي ويخزنه حتى يمكن أن يكون مشكلة.

نصائح أخرى

أعتقد أن _get_single_element يطلق عليه فقط عند استخدام Detype الافتراضي من "كائن". هل حاولت توفير dettype، مثل csr_matrix((data, (i,j)), dtype=int32)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top