لا تعمل إجراءات BLAS الفرعية dgemm وdgemv وddot مع العدديات؟
سؤال
لدي روتين فرعي من Fortran يستخدم إجراءات BLAS الفرعية dgemm وdgemv وddot، والتي تحسب المصفوفة * المصفوفة والمصفوفة * المتجه والمتجه * المتجه.لدي مصفوفات m * m ومتجهات m * 1.في بعض الحالات م = 1.يبدو أن تلك الإجراءات الفرعية لا تعمل بشكل جيد في تلك الحالات.أنها لا تعطي أخطاء، ولكن يبدو أن هناك بعض عدم الاستقرار العددي في النتائج.لذلك لا بد لي من كتابة شيء مثل:
if(m>1) then
vtuni(i,t) = yt(i,t) - ct(i,t) - ddot(m, zt(i,1:m,(t-1)*tvar(3)+1), 1, arec, 1)
else
vtuni(i,t) = yt(i,t) - ct(i,t) - zt(i,1,(t-1)*tvar(3)+1)*arec(1)
لذا فإن سؤالي الفعلي هو، هل أنا على حق في أن الإجراءات الفرعية لـ BLAS لا تعمل بشكل صحيح عندما تكون m=1 أم أن هناك خطأ ما في الكود الخاص بي؟هل يمكن للمترجم أن يؤثر على هذا؟أنا أستخدم جفورتران.
المحلول
من المفترض أن تتصرف إجراءات BLAS بشكل صحيح مع الكائنات ذات الحجم 1.لا أعتقد أنه يمكن أن يعتمد على المترجم، ولكن من الممكن أن يعتمد على تنفيذ BLAS الذي تعتمد عليه (على الرغم من أنني أعتبره خطأ في التنفيذ).المرجع (اقرأ:غير محسّن للهدف) تنفيذ BLAS، والذي يمكن العثور عليه في نتليب, ، يتعامل مع هذه الحالة بشكل جيد.
لقد أجريت بعض الاختبارات على كلا المصفوفتين بالحجم 1، وشرائح الحجم 1 من المصفوفة الأكبر (كما هو الحال في الكود الخاص بك)، وكلاهما يعمل بشكل جيد:
$ cat a.f90 implicit none double precision :: u(1), v(1) double precision, external :: ddot u(:) = 2 v(:) = 3 print *, ddot(1, u, 1, v, 1) end $ gfortran a.f90 -lblas && ./a.out 6.0000000000000000 $ cat b.f90 implicit none double precision, allocatable :: u(:,:,:), v(:) double precision, external :: ddot integer :: i, j allocate(u(3,1,3),v(1)) u(:,:,:) = 2 v(:) = 3 i = 2 j = 2 print *, ddot(1, u(i,1:1,j), 1, v, 1) end $ gfortran b.f90 -lblas && ./a.out 6.0000000000000000
الأشياء التي سأفكر فيها لتصحيح هذه المشكلة بشكل أكبر:
- تأكد من أن الخاص بك
ddot
التعريف صحيح - استبدل المرجع BLAS بالمرجع المُحسّن الخاص بك، للتحقق مما إذا كان يغير أي شيء (يمكنك فقط التجميع والربط في
ddot.f
الملف الذي قمت بربطه مسبقًا في إجابتي)