در علوم کامپیوتر، برنامهنویسی آرایه ای به راه حلهایی اشاره دارد که برنامهها میتوانند توسط آن یک سری عملیات را بر یک مجموعه مقادیر اعمال کنند. اینگونه راه حلها معمولاً در محیطهای علمی و مهندسی مورد استفاده قرار میگیرند.
زبانهای برنامهنویسی مدرن که برنامهنویسی آرایه ای را پشتیبانی میکنند. (همچنین به عنوان زبانهای چند بعدی و برداری شناخته میشوند)
مهندسی شدهاند که بهطور خاص برای تعمیم عملیات در مقیاس به اعمال شفاف در بردارها، ماتریسها، و آرایههای بعدی بالاتر. این موارد شامل APL , J، Fortran 90، Mata , MATLAB , Analytica , TK Solver (به صورت لیست)، Octave , R، Cilk Plus , Julia , Perl Data Language (PDL) و پسوند NumPy به پایتون است. در این زبانها، عملیاتی که روی کل آرایهها عمل میکند را میتوان یک عمل بردار نامید ، [۱] صرف نظر از اینکه روی پردازنده برداری اجرا میشود که دستورالعملهای برداری را اجرا میکند. برنامهنویسی آرایه بهطور خلاصه ایدههای گستردهای را دربارهٔ دستکاری داده بیان میکند. سطح جمعبندی در موارد خاص میتواند چشمگیر باشد: یافتن زبان برنامهنویسی آرایه یک خطی که به چندین صفحه کد شی گرا نیاز دارد، غیرمعمول نیست.
رتبه تابع یک مفهوم مهم برای زبانهای برنامهنویسی آرایه بهطور کلی، به قیاس با رتبه تانسور در ریاضیات است: توابع که بر روی دادهها کار میکنند، ممکن است براساس تعداد ابعادی که عمل میکنند، طبقهبندی شوند. به عنوان مثال ضرب معمولی، یک تابع دارای رتبهبندی مقیاسی است زیرا با دادههای صفر بعدی (اعداد منفرد) کار میکند. عملکرد محصول متقاطع نمونه ای از یک تابع مرتبه برداری است زیرا از طریق بردارها عمل میکند نه مقیاس پذیرها. ضرب ماتریس مثالی از یک تابع ۲ درجه ای است، زیرا روی اشیا ۲ ۲ بعدی (ماتریس) عمل میکند. عملگرهای جمعآوری ابعاد آرایه داده ورودی را با یک یا چند بعد کاهش میدهند. به عنوان مثال، جمع کردن عناصر، آرایه ورودی را با ۱ بعد جمع میکند.
استفادهها
برنامهنویسی آرایه برای موازی سازی ضمنی بسیار مناسب است. امروزه موضوع بسیاری از تحقیقات است بعلاوه، اینتل و پردازندههای سازگار پس از ۱۹۹۷ تولید و تولید شدند که حاوی پسوندهای مختلف مجموعه دستورالعملها بودند، از MMX شروع میشوند و از طریق SSSE3 و 3DNow ادامه مییابند!، که شامل قابلیتهای اولیه آرایه SIMD است. پردازش آرایه از پردازش موازی متمایز است به این دلیل که یک پردازنده فیزیکی بهطور همزمان بر روی گروهی از موارد کار میکند در حالی که پردازش موازی با هدف تقسیم یک مسئله بزرگتر به مشکلات کوچکتر (MIMD) انجام میشود تا توسط پردازندههای متعدد به صورت قطعه ای حل شود. پردازندههای دارای دو یا چند هسته امروزه بهطور فزاینده ای معمول هستند.
زبانهای برنامهنویسی
نمونههای متعارف زبانهای برنامهنویسی آرایه Fortran، APL و J هستند. سایر موارد عبارتند از: A +، Analytica , Chapel , IDL، جولیا، K , Klong , Q، Mata، MATLAB , MOLSF، NumPy، GNU Octave , PDL، R , S-Lang , SAC , Nial , ZPL و TI-BASIC.
زبانهای اسکالر
در زبانهای اسکالر مانند C و Pascal، اعمال فقط در مقادیر منفرد اعمال میشوند، بنابراین a + b جمع دو عدد را بیان میکند. در چنین زبانهایی، افزودن یک آرایه به دیگری به نمایه سازی و حلقه نیاز دارد، کدگذاری آن خسته کننده است.
for (i = 0; i <n; i++)
for (j = 0; j <n; j++)
a[i][j] += b[i][j];
در زبانهای مبتنی بر آرایه، به عنوان مثال در Fortran، حلقه تو در تو در بالا میتواند در قالب آرایه در یک خط نوشته شود،
یا به جای آن، برای تأکید بر ماهیت آرایه اشیا،
زبانهای آرایه ای
در زبانهای آرایه، عملکردها به گونه ای تعمیم یافتهاند که هم در مقیاس کشها و هم در آرایهها اعمال میشوند؛ بنابراین، a + b مجموع دو مقیاس دهنده را نشان میدهد اگر a و b مقیاس آور باشند، یا مجموع دو آرایه را اگر آرایه ای باشند بیان میکند.
زبان آرایه برنامهنویسی را ساده میکند اما احتمالاً با هزینه ای است که به عنوان جریمه انتزاع شناخته میشود.[۱][۲] از آنجا که اضافات جدا از بقیه برنامهنویسی انجام میشود، ممکن است کارآمدترین کد را تولید نکند. (به عنوان مثال، ممکن است متعاقباً در طی همان اجرا، اضافه شدن عناصر دیگر از همان آرایه، باعث جستجوهای مکرر غیرضروری شود) حتی پیچیدهترین کامپایلر بهینهسازی نیز در تلفیق دو یا چند عملکرد ظاهراً متفاوت که ممکن است در بخشهای مختلف برنامه یا زیر روال ظاهر شود، بسیار دشوار خواهد بود، حتی اگر یک برنامهنویس میتواند این کار را به راحتی انجام دهد، مبالغی را در همان عبور از آرایه جمع میکند برای به حداقل رساندن سربار)
کد C قبلی در زبان Ada به صورت زیر در میآید[۳] که از نحو برنامهنویسی آرایه پشتیبانی میکند.
APL
APL از نمادهای Unicode تک کاراکتر و بدون قند نحوی استفاده میکند.
این عملیات روی آرایههای با هر درجه (از جمله رتبه ۰) و روی مقیاس و آرایه کار میکند. Dyalog APL زبان اصلی را با تکالیف افزوده گسترش میدهد:
آنالیتیکا(Analytica)
Analytica همان اقتصاد بیان Ada را فراهم میکند.
A := A + B;
BASIC
دارتموث BASIC در ویرایش سوم (۱۹۶۶) عبارات MAT برای دستکاری ماتریس و آرایه داشت.
DIM A(4),B(4),C(4)
MAT A = 1
MAT B = 2 * A
MAT C = A + B
MAT PRINT A,B,C
ماتا(MATA)
Stata که زبان برنامهنویسی ماتریس برنامهنویسی ماتا پشتیبانی آرایه است. در زیر، جمع، ضرب، جمع ماتریس و مقیاس، ضریب عنصر به عنصر، اشتراک و یکی از بسیاری از توابع ماتریس معکوس ماتا را نشان میدهیم.
. mata:
: A = (1,2,3) \(4,5,6)
: A
1 2 3
+----+
1 | 1 2 3 |
2 | 4 5 6 |
+----+
: B = (2..4) \(1..3)
: B
1 2 3
+----+
1 | 2 3 4 |
2 | 1 2 3 |
+----+
: C = J(3,2,1) // A 3 by 2 matrix of ones
: C
1 2
+----+
1 | 1 1 |
2 | 1 1 |
3 | 1 1 |
+----+
: D = A + B
: D
1 2 3
+----+
1 | 3 5 7 |
2 | 5 7 9 |
+----+
: E = A*C
: E
1 2
+----+
1 | 6 6 |
2 | 15 15 |
+----+
: F = A:*B
: F
1 2 3
+----+
1 | 2 6 12 |
2 | 4 10 18 |
+----+
: G = E :+ 3
: G
1 2
+----+
1 | 9 9 |
2 | 18 18 |
+----+
: H = F[(2\1), (1, 2)] // Subscripting to get a submatrix of F and
: // switch row 1 and 2
: H
1 2
+----+
1 | 4 10 |
2 | 2 6 |
+----+
: I = invsym(F'*F) // Generalized inverse (F*F^(-1)F=F) of a
: // symmetric positive semi-definite matrix
: I
[symmetric]
1 2 3
+----+
1 | 0 |
2 | 0 3.25 |
3 | 0 -1.75 .9444444444 |
+----+
: end
متلب (MATLAB)
پیادهسازی در MATLAB همان اقتصاد مجاز را با استفاده از زبان Fortran فراهم میکند.
نوع دیگری از زبان MATLAB زبان GNU Octave است که زبان اصلی را با تکالیف افزوده گسترش میدهد:
هر دو MATLAB و GNU Octave بومی عمل جبر خطی مانند ضرب ماتریس، وارونگی ماتریس و حل عددی سیستم معادلات خطی را پشتیبانی میکنند، حتی با استفاده از شبه معکوس مور-پنروز.[۴][۵]
نمونه Nial از محصول داخلی دو آرایه را میتوان با استفاده از عملگر ضرب ماتریس بومی پیادهسازی کرد. اگر a
بردار ردیفی به اندازه [1 n] باشد و b
بردار ستونی مربوط به اندازه [n 1] باشد.
a * b؛
این محصول داخلی بین دو ماتریس نیاز به همان تعداد از عناصر را میتوان با استفاده از عملگر کمکی اجرا (:)
، که باعث تغییر شکل یک ماتریس داده شده را به بردار، و ترانهاده اپراتور '
:
A(:)' * B(:);
راسکل(Rasql)
زبان پرس و جو rasdaman یک زبان برنامهنویسی آرایه ای پایگاه داده است. به عنوان مثال، دو آرایه میتوانند با پرس و جو زیر اضافه شوند:
R
زبان R بهطور پیش فرض از الگوی آرایه پشتیبانی میکند. مثال زیر فرایند ضرب دو ماتریس و به دنبال آن اضافه کردن یک اسکالر (که در واقع یک بردار یک عنصر است) و یک بردار را نشان میدهد:
> A <- matrix(1:6, nrow=2) !!this has nrow=2 ... and A has 2 rows
> A
[,1] [,2] [,3]
[1,] 1 3 5
[2,] 2 4 6
> B <- t( matrix(6:1, nrow=2) ) # t() is a transpose operator !!this has nrow=2 ... and B has 3 rows --- a clear contradiction to the definition of A
> B
[,1] [,2]
[1,] 6 5
[2,] 4 3
[3,] 2 1
> C <- A %*% B
> C
[,1] [,2]
[1,] 28 19
[2,] 40 28
> D <- C + 1
> D
[,1] [,2]
[1,] 29 20
[2,] 41 29
> D + c(1, 1) # c() creates a vector
[,1] [,2]
[1,] 30 21
[2,] 42 30
عملگر تقسیم چپ ماتریس بهطور خلاصه برخی از خصوصیات معنایی ماتریسها را بیان میکند. همانند معادل اسکالر، اگر ضریب (تعیین کننده) ضریب (ماتریس) A
صفر نباشد، میتوان معادله (بردار) A * x = b
با ضرب چپ هر دو طرف برعکس A
: A −1
(به دو زبان MATLAB و GNU Octave: A^-1
). عبارات ریاضی زیر هنگامی که A
یک ماتریس مربع درجه کامل است نگه داشته میشوند:
A^-1 *(A * x)==A^-1 * (b)
(A^-1 * A)* x ==A^-1 * b
(ماتریس ضرب associativity)
x = A^-1 * b
جایی که
عملگر رابطه ای برابر است. عبارات قبلی همچنین عبارات معتبر MATLAB هستند اگر عبارت سوم قبل از موارد دیگر اجرا شود (مقایسه عددی ممکن است نادرست باشد به دلیل خطاهای دور زدن).
اگر سیستم بیش از حد تعیین شده باشد - به طوری که A
بیشتر از ستونها باشد - معکوس شبه A +
(به زبان MATLAB و GNU Octave: pinv(A)
) میتواند معکوس A −1
را جایگزین کند، به شرح زیر:
pinv(A) *(A * x)==pinv(A) * (b)
(pinv(A) * A)* x ==pinv(A) * b
(تداخل ضرب ماتریس)
x = pinv(A) * b
با این حال، این راه حلها نه مختصرترین راه حلها هستند (به عنوان مثال هنوز هم نیاز به تمایز نمایی سیستمهای بیش از حد تعیین شده باقی مانده است) و نه کارآمدترین محاسبات. درک آخرین نکته آسان است هنگام بررسی مجدد معادل اسکالر a * x = b
، که برای آن راه حل x = a^-1 * b
x = b / a
به دو عمل نیاز دارد. مشکل این است که بهطور کلی ضرب ماتریس می مبادلهای به عنوان گسترش راه حل عددی به صورت ماتریس نیاز:
(a * x)/ a ==b / a
(x * a)/ a ==b / a
(اشتراکی برای ماتریسها صدق نمیکند!)
x * (a / a)==b / a
(تداعی برای ماتریسها نیز وجود دارد)
x = b / a
زبان MATLAB معرفی اپراتور چپ تقسیم \
برای حفظ بخش اساسی از قیاس با مورد اسکالر، بنابراین ساده استدلال ریاضی و حفظ اختصار:
A \ (A * x)==A \ b
(A \ A)* x ==A \ b
(انجمنی برای ماتریسها نیز وجود دارد، دیگر نیازی به اشتراکی نیست)
x = A \ b
این نه تنها نمونه ای از برنامهنویسی آرایه مختصر از نظر کدگذاری بلکه از منظر کارایی محاسباتی است که در چندین زبان برنامهنویسی آرایه از کتابخانههای جبر خطی کاملاً کارآمد مانند ATLAS یا LAPACK سود میبرد.[۶]
Returning to the previous quotation of Iverson, the rationale behind it should now be evident:
it is important to distinguish the difficulty of describing and of learning a piece of notation from the difficulty of mastering its implications. For example, learning the rules for computing a matrix product is easy, but a mastery of its implications (such as its associativity, its distributivity over addition, and its ability to represent linear functions and geometric operations) is a different and much more difficult matter.
Indeed, the very suggestiveness of a notation may make it seem harder to learn because of the many properties it suggests for explorations.
کتابخانههای شخص ثالث (third-party)
استفاده از کتابخانههای تخصصی و کارآمد برای ارائه تجریدات مختصر در سایر زبانهای برنامهنویسی نیز معمول است. در C ++ چندین کتابخانه جبر خطی از توانایی زبان در اضافه بار اپراتورها سو explo استفاده میکنند. در بعضی موارد ، انتزاع بسیار ناچیز در آن زبانها به صراحت تحت تأثیر الگوی برنامهنویسی آرایه قرار میگیرد، همانطور که کتابخانههای ++ Armadillo و Blitz این کار را میکنند.[۷][۸]
جستارهای وابسته
منابع
پیوند به بیرون