나는 이 기사를 읽고 있었고 ,이 사람은 모든 사람들이 데이터 지향 디자인과 OOP를 혼합하여 어떻게 혜택을 볼 수 있는지에 대해 이야기합니다. 그러나 코드 샘플은 표시하지 않습니다.
나는 이것을 봤고 코드 샘플은 말할 것도없이 이것이 무엇인지에 대한 실제 정보를 찾을 수 없었다. 이 용어에 익숙하고 예를 제공 할 수있는 사람이 있습니까? 이것은 다른 단어일까요?
나는 이 기사를 읽고 있었고 ,이 사람은 모든 사람들이 데이터 지향 디자인과 OOP를 혼합하여 어떻게 혜택을 볼 수 있는지에 대해 이야기합니다. 그러나 코드 샘플은 표시하지 않습니다.
나는 이것을 봤고 코드 샘플은 말할 것도없이 이것이 무엇인지에 대한 실제 정보를 찾을 수 없었다. 이 용어에 익숙하고 예를 제공 할 수있는 사람이 있습니까? 이것은 다른 단어일까요?
답변:
우선, 이것을 데이터 중심 디자인과 혼동하지 마십시오.
Data Oriented Design에 대한 나의 이해는 효율적인 처리를 위해 데이터를 구성하는 것입니다. 특히 캐시 미스 등과 관련하여 데이터 중심 디자인은 데이터가 많은 프로그램 동작을 제어하도록하는 것입니다 ( Andrew Keith의 답변에 잘 설명되어 있음 ).
색상, 반경, 탄력성, 위치 등과 같은 속성을 가진 응용 프로그램에 공 개체가 있다고 가정 해보십시오.
객체 지향 접근
OOP에서는 다음과 같이 공을 설명합니다.
class Ball {
Point position;
Color color;
double radius;
void draw();
};
그런 다음 다음과 같이 공 모음을 만듭니다.
vector<Ball> balls;
데이터 지향 접근법
그러나 데이터 지향 디자인에서는 다음과 같은 코드를 작성할 가능성이 높습니다.
class Balls {
vector<Point> position;
vector<Color> color;
vector<double> radius;
void draw();
};
보시다시피 더 이상 하나의 볼을 나타내는 단일 유닛이 없습니다. 볼 객체는 암시 적으로 만 존재합니다.
이것은 성능 측면에서 많은 장점을 가질 수 있습니다. 일반적으로 우리는 동시에 많은 볼에서 작업을 수행하려고합니다. 하드웨어는 일반적으로 효율적으로 작동하기 위해 큰 연속 메모리 청크를 원합니다.
둘째, 볼 속성의 일부에만 영향을주는 작업을 수행 할 수 있습니다. 예를 들어 모든 볼의 색상을 다양한 방법으로 결합하면 캐시에 색상 정보 만 포함 시키려고합니다. 그러나 모든 볼 속성이 하나의 유닛에 저장되면 볼의 다른 모든 속성도 가져옵니다. 필요하지 않더라도.
캐시 사용 예
각 볼이 64 바이트를 차지하고 포인트가 4 바이트를 차지한다고 가정 해보십시오. 캐시 슬롯에는 64 바이트도 필요합니다. 10 볼의 위치를 업데이트하려면 10 * 64 = 640 바이트의 메모리를 캐시로 가져와 10 캐시 누락을 가져와야합니다. 그러나 볼의 위치를 별도의 단위로 작업 할 수 있다면 4 * 10 = 40 바이트 만 걸립니다. 하나의 캐시 페치에 적합합니다. 따라서 우리는 10 개의 공을 모두 업데이트하기 위해 1 개의 캐시 미스 만 얻습니다. 이 숫자는 임의적입니다-캐시 블록이 더 크다고 가정합니다.
그러나 메모리 레이아웃이 캐시 적중에 미치는 영향과 성능에 미치는 영향을 보여줍니다. CPU와 RAM 속도의 차이가 커짐에 따라 중요도가 높아집니다.
메모리를 레이아웃하는 방법
내 공 예제에서는 일반적으로 모든 일반 앱의 경우 여러 변수에 함께 액세스 할 수 있기 때문에 문제를 많이 단순화했습니다. 예를 들어 위치와 반경이 자주 사용됩니다. 그런 다음 구조는 다음과 같아야합니다.
class Body {
Point position;
double radius;
};
class Balls {
vector<Body> bodies;
vector<Color> color;
void draw();
};
이렇게해야하는 이유는 함께 사용 된 데이터가 별도의 어레이에 배치 될 경우 캐시의 동일한 슬롯에 대해 경쟁 할 위험이 있기 때문입니다. 따라서 하나를로드하면 다른 하나를 버릴 것입니다.
따라서 객체 지향 프로그래밍과 비교하여 최종적으로 만드는 클래스는 문제의 정신 모델에있는 엔터티와 관련이 없습니다. 데이터 사용량을 기준으로 데이터가 함께 모이기 때문에 항상 데이터 지향 디자인에서 클래스를 제공 할 수있는 합리적인 이름이있는 것은 아닙니다.
관계형 데이터베이스와의 관계
Data Oriented Design의 기본 개념은 관계형 데이터베이스에 대한 생각과 매우 유사합니다. 이 경우 캐시는 CPU 캐시가 아니라 메모리의 페이지이지만 관계형 데이터베이스 최적화에는 캐시를보다 효율적으로 사용하는 것이 포함될 수도 있습니다. 훌륭한 데이터베이스 디자이너는 열 수가 많은 테이블을 만들지 않고 자주 액세스하지 않는 데이터를 별도의 테이블로 분할 할 수도 있습니다. 또한 디스크의 여러 위치에서 데이터에 액세스 할 필요가 없도록 일부 테이블을 비정규 화하도록 선택할 수도 있습니다. Data Oriented Design과 마찬가지로 이러한 선택은 데이터 액세스 패턴과 성능 병목 현상의 위치를 확인하여 수행됩니다.
struct balls {vector<vec3> pos; vector<vec3> velocity;}
속도 벡터와 위치 벡터 사이에서 앞뒤로 움직이므로 각 볼의 위치를 업데이트하지 않는다는 구조가 있다고 가정 해 봅시다. 또한 단지 그림)?
struct balls { vector<color> colors; vector<body> bodies; /* contains position and velocity */ }
입니다.
Mike Acton은 최근 데이터 지향 디자인 에 대한 공개 연설을 했습니다.
기본 요약은 다음과 같습니다. 성능을 원한다면 데이터 흐름에 대해 생각하고 나사로 조일 가능성이 가장 높은 스토리지 계층을 찾아 하드에 최적화하십시오 . Mike는 실시간으로 L2 캐시 누락에 중점을두고 있지만 데이터베이스 (디스크 읽기) 및 웹 (HTTP 요청)에도 동일한 사항이 적용된다고 생각합니다. 시스템 프로그래밍을 수행하는 유용한 방법이라고 생각합니다.
알고리즘과 시간 복잡성에 대해 생각하는 것을 막을 수는 없으며 미친 CS 기술로 타겟팅 해야하는 가장 비싼 작업 유형을 파악하는 데주의를 기울입니다.
노엘이 우리가 게임 개발에서 직면 한 특정 요구에 대해 구체적으로 이야기하고 있음을 지적하고 싶습니다. 실시간 소프트 시뮬레이션을 수행하는 다른 부문에서이 기능을 활용할 수 있다고 생각하지만 일반적인 비즈니스 응용 프로그램을 눈에 띄게 개선하는 기술은 아닐 것입니다. 이 설정은 모든 마지막 성능 비트가 기본 하드웨어에서 압축되도록하기위한 것입니다.
데이터 지향 디자인은 응용 프로그램의 논리가 절차 알고리즘 대신 데이터 세트로 구성되는 디자인입니다. 예를 들어
절차 적 접근.
int animation; // this value is the animation index
if(animation == 0)
PerformMoveForward();
else if(animation == 1)
PerformMoveBack();
.... // etc
데이터 디자인 접근법
typedef struct
{
int Index;
void (*Perform)();
}AnimationIndice;
// build my animation dictionary
AnimationIndice AnimationIndices[] =
{
{ 0,PerformMoveForward }
{ 1,PerformMoveBack }
}
// when its time to run, i use my dictionary to find my logic
int animation; // this value is the animation index
AnimationIndices[animation].Perform();
이와 같은 데이터 디자인은 응용 프로그램의 논리를 구축하기 위해 데이터 사용을 촉진합니다. 애니메이션이나 다른 요소를 기반으로 수천 개의 논리 경로를 가질 수있는 비디오 게임에서 특히 관리하기가 더 쉽습니다.