배열 프로그래밍

프로그래밍 패러다임 컴퓨터 과학에서 **배열 프로그래밍**(Array programming, 어레이 프로그래밍)은 전체 값 집합에 대해 한 번에 연산을 적용할 수 있는 솔루션을 의미한다. 이러한 솔루션은 일반적으로 계산과학 및 엔지니어링 환경에서 사용된다. 배열 프로그래밍을 지원하는 최신 프로그래밍 언어(또는 벡터 또는 다차원 언어라고도 함)는 스칼라에 대한 연산을 벡터, 행렬, 그리고 고차원 배열에 투명하게 적용하도록 특별히 설계되었다. 여기에는 APL, J, 포트란, 매트랩, Analytica, GNU 옥타브, R, 실크 플러스, 줄리아, 펄 데이터 언어(PDL), 라쿠가 포함된다. 이 언어들에서 전체 배열에 대해 작동하는 연산을 벡터화된 연산이라고 부를 수 있으며,s2cid=16907816 벡터 프로세서에서 실행되는지 여부와는 관계없이 벡터 명령을 구현한다. 배열 프로그래밍 프리미티브는 데이터 조작에 대한 광범위한 아이디어를 간결하게 표현한다. 간결성의 수준은 특정 경우에 극적일 수 있다. 객체 지향 코드 몇 페이지를 요구하는 배열 프로그래밍 언어 원 라이너를 흔히 볼 수 있다.
# 배열의 개념
배열 프로그래밍의 기본 아이디어는 연산이 한 번에 전체 값 집합에 적용된다는 것이다. 이는 프로그래머가 개별 스칼라 연산의 명시적 루프에 의존할 필요 없이 전체 데이터 집합을 생각하고 조작할 수 있도록 해주기 때문에 고급 프로그래밍 모델이 된다. 케네스 아이버슨은 배열 프로그래밍(실제로는 APL을 지칭)의 근거를 다음과 같이 설명했다.doi-access= free 대부분의 프로그래밍 언어는 수학적 표기법에 비해 현저히 떨어지며, 응용 수학자들이 중요하다고 여길 만한 방식으로 사고 도구로 거의 사용되지 않는다. 본 논문의 요지는 프로그래밍 언어에서 발견되는 실행 가능성 및 보편성의 장점을 수학적 표기법이 제공하는 장점과 하나의 일관된 언어 내에서 효과적으로 결합할 수 있다는 것이다. 표기법을 묘사하고 배우는 어려움과 그 함의를 숙달하는 어려움을 구별하는 것이 중요하다. 예를 들어, 행렬 곱셈의 규칙을 배우는 것은 쉽지만, 그 함의(예: 결합성, 덧셈에 대한 분배성, 선형 함수 및 기하학적 연산을 나타내는 능력)를 숙달하는 것은 다르고 훨씬 더 어려운 문제이다. 실제로 표기법의 시사성은 탐색을 위해 제안하는 많은 속성 때문에 배우기 더 어렵게 만들 수도 있다. [...] 컴퓨터 및 프로그래밍 언어 사용자는 종종 알고리즘 실행의 효율성에 주로 관심을 가지므로, 여기에 제시된 많은 알고리즘을 즉시 기각할 수 있다. 이러한 기각은 단기적인 시각이다. 왜냐하면 알고리즘의 명확한 서술은 일반적으로 더 효율적인 알고리즘을 쉽게 도출할 수 있는 기반으로 사용될 수 있기 때문이다. 배열 프로그래밍 및 사고의 기본은 개별 요소가 유사하거나 인접한 데이터의 속성을 찾아 활용하는 것이다. 데이터를 구성 요소(또는 스칼라 양)로 암묵적으로 분해하는 객체 지향과 달리, 배열 지향은 데이터를 그룹화하고 균일하게 처리하려고 한다. 함수 랭크는 일반적으로 배열 프로그래밍 언어에 중요한 개념이며, 수학의 텐서 랭크에 비유할 수 있다. 데이터에 대해 작동하는 함수는 작동하는 차원의 수에 따라 분류될 수 있다. 예를 들어, 일반적인 곱셈은 0차원 데이터(개별 숫자)에 대해 작동하므로 스칼라 랭크 함수이다. 벡터곱 연산은 스칼라가 아닌 벡터에 대해 작동하므로 벡터 랭크 함수의 예이다. 행렬 곱셈은 2차원 객체(행렬)에 대해 작동하므로 2랭크 함수의 예이다. 축소 연산자는 입력 데이터 배열의 차원을 하나 이상 줄인다. 예를 들어, 요소에 대한 합계는 입력 배열을 1차원 줄인다.
# 사용법
배열 프로그래밍은 암묵적 병렬화에 매우 적합하다. 이는 오늘날 많은 연구가 진행되는 주제이다. 또한, 1997년 이후 개발 및 생산된 인텔 및 호환 CPU는 MMX부터 시작하여 SSSE3 및 3D나우!까지 다양한 명령어 집합 확장을 포함했으며, 이는 기본적인 단일 명령 다중 데이터 배열 기능을 포함한다. 이는 2020년대까지 AVX-512와 같은 명령어 집합으로 이어져 현대 CPU를 정교한 벡터 프로세서로 만들고 있다. 배열 처리는 병렬 처리와 구별된다. 배열 처리에서는 하나의 물리적 프로세서가 항목 그룹에 대해 동시에 연산을 수행하는 반면, 병렬 처리는 더 큰 문제를 더 작은 문제(다중 명령 다중 데이터)로 분할하여 여러 프로세서가 조각별로 해결하는 것을 목표로 한다. 2023년 현재 다중 코어 프로세서와 수천 개의 범용 컴퓨팅 코어를 갖춘 GPU가 일반적이다.
# 언어
배열 프로그래밍 언어의 전형적인 예는 포트란, APL, J이다. 다른 언어로는 A+, Analytica, 채플, 대화형 데이터 언어, 줄리아, K, Klong, Q, 매트랩, GNU 옥타브, 싸이랩, FreeMat, 펄 데이터 언어(PDL), R, 라쿠, S-Lang, SAC, Nial, ZPL, Futhark, 그리고 TI-BASIC이 있다.
## 스칼라 언어
C 및 파스칼과 같은 스칼라 언어에서는 연산이 단일 값에만 적용되므로 a+b는 두 숫자의 덧셈을 표현한다. 이러한 언어에서 한 배열을 다른 배열에 더하려면 인덱싱과 루프가 필요하며, 이는 코딩하기 번거롭다. for (i = 0; i A A [,1] [,2] [,3] [1,] 1 3 5 [2,] 2 4 6 > B B [,1] [,2] [1,] 6 5 [2,] 4 3 [3,] 2 1 > C C [,1] [,2] [1,] 28 19 [2,] 40 28 > D 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
### 라쿠
라쿠는 메타 연산자를 통해 배열 패러다임을 지원한다.title=Metaoperators section of Raku Operator documentation 다음 예제는 더하기 연산자와 함께 하이퍼 연산자를 사용하여 배열 @a와 @b를 더하는 것을 보여준다. [0] > my @a = [[1,1],[2,2],[3,3]]; [[1 1] [2 2] [3 3]] [1] > my @b = [[4,4],[5,5],[6,6]]; [[4 4] [5 5] [6 6]] [2] > @a »+« @b; [[5 5] [7 7] [9 9]]
# 수학적 추론과 언어 표기법
행렬 왼쪽 나눗셈 연산자는 행렬의 일부 의미론적 속성을 간결하게 표현한다. 스칼라 등가물과 마찬가지로, 계수 (행렬) `A`의 (행렬식이) 널이 아니면 양변에 `A`의 역행렬 `A−1` (매트랩 및 GNU 옥타브 언어에서 `A^-1`)를 왼쪽에서 곱하여 (벡터) 방정식 `A * x = b`를 풀 수 있다. 다음 수학적 진술은 `A`가 풀 랭크 정사각 행렬일 때 유효하다. :`A^-1 *(A * x)
# A^-1 * (b)` :`(A^-1 * A)* x
A^-1 * b ` (행렬 곱셈 결합성) :`x = A^-1 * b` 여기서 `==`는 동등 관계연산자이다. 이전 진술은 세 번째가 다른 것들보다 먼저 실행되면 유효한 매트랩 표현식이기도 하다 (반올림 오류로 인해 수치 비교가 거짓일 수 있음). 만약 시스템이 과결정되어 `A`가 열보다 행이 많다면, 유사역행렬 `A+` (매트랩 및 GNU 옥타브 언어에서는 `pinv(A)`)가 역행렬 `A−1`를 대체할 수 있다. :1=pinv(A) *(A * x)==pinv(A) * (b) :1=(pinv(A) * A)* x ==pinv(A) * b (행렬 곱셈 결합성) :1=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` 매트랩 언어는 스칼라 사례와의 유사성의 본질적인 부분을 유지하기 위해 왼쪽 나눗셈 연산자 `\`를 도입하여 수학적 추론을 단순화하고 간결성을 보존한다. :`A \ (A * x)
# A \ b` :`(A \ A)* x
A \ b` (결합성은 행렬에 대해서도 성립하며, 교환성은 더 이상 필요하지 않다) :`x = A \ b` 이는 코딩 관점에서 간결한 배열 프로그래밍의 예일 뿐만 아니라 계산 효율성 측면에서도 그러하다. 여러 배열 프로그래밍 언어에서는 ATLAS 또는 LAPACK과 같은 매우 효율적인 선형 대수 라이브러리의 이점을 누린다.access-date= 2011-03-19 아이버슨의 이전 인용으로 돌아가면, 그 뒤에 숨겨진 근거는 이제 명백해질 것이다. 표기법을 묘사하고 배우는 어려움과 그 함의를 숙달하는 어려움을 구별하는 것이 중요하다. 예를 들어, 행렬 곱셈의 규칙을 배우는 것은 쉽지만, 그 함의(예: 결합성, 덧셈에 대한 분배성, 선형 함수 및 기하학적 연산을 나타내는 능력)를 숙달하는 것은 다르고 훨씬 더 어려운 문제이다. 실제로 표기법의 시사성은 탐색을 위해 제안하는 많은 속성 때문에 배우기 더 어렵게 만들 수도 있다.
# 타사 라이브러리
더 간결한 추상화를 제공하기 위해 특수하고 효율적인 라이브러리를 사용하는 것은 다른 프로그래밍 언어에서도 흔히 볼 수 있다. C++에서는 여러 선형대수 라이브러리가 언어의 연산자 오버로딩 기능을 활용한다. 어떤 경우에는 파이썬의 NumPy 확장 라이브러리, 아르마딜로 및 Blitz++ 라이브러리가 그러하듯이, 이러한 언어에서 매우 간결한 추상화가 배열 프로그래밍 패러다임의 명시적인 영향을 받는다.access-date= 2011-03-19url-status= dead