 |  |
|
난이도 : 중급 Jonathan Bartlett, Director of Technology, New Medio
2007 년 5 월 08 일 Sony® PLAYSTATION® 3 (PS3)는 프로그래머가 새로운 Cell Broadband Engine™ (Cell BE) 프로세서를 접할 수 있는 가장 쉽고 저렴한 방법입니다. PS3에 리눅스®를 설치하는 방법, PS3에서 Cell BE 프로세서를 기반으로 한 개발 방법을 설명합니다.
PLAYSTATION 3는 게임 콘솔로는 두가지의 이례적인 면을 가지고 있다. 우선, 이전의 어떤 콘솔보다 엄청나게 개방되어 있다. 대부분의 게임 콘솔들은 인증되지 않는 게임이 해당 시스템에서 작동하지 못하도록 하는 반면, , PS3는 그 반대이다. 심지어, 다른 OS의 설치와 부팅을 직접적으로 지원하기도 한다. 비디오 가속기와 같은 기능들은 서드 파티 OS에 한정되므로 이 시리즈에서는 범용적이며 과학적인 애플리케이션에 초점을 맞춰 설명하겠다.
PS3의 중심은 프로세서, 즉 Cell Broadband Engine 칩(Cell BE 칩)이다. Cell BE 아키텍처는 전통적인 프로세서 디자인에서 과감히 탈피했다. Cell BE 프로세서는 아홉 개의 프로세싱 엘리먼트들로 구성된 칩이다. (PS3는 시스템용 1개와 비활성화된 1개 외에 나머지 일곱 개를 사용할 수 있다.) 메인 프로세싱 엘리먼트는 표준의 범용 프로세서이다. 이것은 Power Processing Element(PPE)라고 하는 듀얼 코어 PowerPC® 기반 엘리먼트이다. 다른 여덟 개의 프로세싱 엘리먼트는 또 다른 방식이다.
Cell BE 내의 기타 다른 프로세싱 엘리먼트들은 Synergistic
Processing Elements(SPE)로 알려져 있다. 각각의 SPE의 구성 요소는 다음과 같다.
- Synergistic Processing Unit(SPU)라고 하는 벡터 프로세서
- 로컬 스토어(local store)라고 하는 SPU 내의 전용 메모리 영역 (PS3에서 이 영역의 크기는 256K이다.)
- 외부 세계를 다루는 통신 채널 세트
- 128비트 레지스터. (각 레지스터는 네 개의 32 비트 값을 동시에 보유하는 것으로 간주된다.)
- SPU의 로컬 스토어와 메인 메모리 사이의 DMA 전송을 관리하는 Memory Flow Controller(MFC)
하지만, SPE는 프로세서가 일반적으로 갖고있는 범용 기능이 매우 부족하다. 일반적인 OS 태스크를 수행할 수 없다. 가상 메모리 지원도 되지 않으며, 컴퓨터의 RAM으로 직접적인 액세스를 할 수 없고, 인터럽트 지원도 매우 제한되었다. 이러한 프로세서들은 가능한 빠르게 데이터를 처리하는데 집중한다.
따라서, PPE는 리소스 매니저의 역할을 하고, SPE는 데이터 크런처(cruncher)의 역할을 한다. PPE 상의 프로그램들은 태스크들을 SPE로 분배하고, 데이터를 서로 주고 받는다.
SPE, PPE, 메인 메모리 컨트롤러로 연결하는 것은 Element Interconnect Bus이다. 이것은 데이터가 이동하는 메인 통로가 된다.
이 디자인의 가장 놀라운 부분은 SPE의 256K 로컬 스토어가 캐시(cache)가 아니라는 점이다. 이것은 실제로 SPE가 프로그램과 데이터를 위해 사용해야 하는 총 메모리이다. 단점처럼 보이지만, 여러 가지 장점들도 있다.
- 로컬 스토어 메모리 액세스들은 메인 메모리 액세스에 비해서 매우 빠르다.
- 로컬 스토어 메모리로의 액세스는 클록 사이클(clock cycle)까지 예견될 수 있다.
- 메인 메모리 안팎으로 데이터 이동은 비동기식으로 요청될 수 있으며 예정보다 일찍 예견된다.
기본적으로, 캐시의 모든 속도의 장점을 가진다. 하지만, 프로그램은 이것을 직접적이고 분명하게 사용하기 때문에 이것이 관리되는 방법에 대해 훨씬 더 잘 알고 있다. 데이터가 필요하기 전에 데이터 로딩을 요청할 수 있고, 데이터가 로딩되기를 기다리는 동안 다른 태스크들을 수행한다.
Cell BE 프로세서는 한동안 특수한 하드웨어 전용이었지만, PS3에와서는 최초로 쉽게 사용 할 수 있는 Cell BE 기반 장치가 되었으며 리눅스에서 원하는 누구나 프로그래밍 할 수 있다.
리눅스를 구동하는가? 어떻게 하는가?
게임 콘솔에서 다른 OS 설치를 허용한다는 것은 이례적인 일이다. 콘솔은 보통 원가 이하로 판매되기 때문에 콘솔 개발자에게 로열티를 지불하지 않고는 그 콘솔에서 게임을 실행할 수 없도록 잠금을 걸어둔다. Sony는 PS3 콘솔을 일부 개방하고 서드 파티 OS의 설치를 허용할 것을 결정했다. 하지만 고급 그래픽을 사용할 수 없다는 제약이 있다.
이러한 이유로, 여러분은 PS3에서 리눅스를 설치하고 확실히 작동 시킬 수 있다. Terra Soft Solutions는 Sony와 협력하여 PS3 전용의 Yellow Dog Linux 5를 개발했다. 다른 배포판들과는 달리 PS3에서 사용할 수 있도록 지원이 된다. Yellow Dog Linux (이하 YDL)는 원래 PowerPC 기반의 배포판이었기 때문에, Sony가 YDL의 다음 버전을 PS3에 맞춰 개발하기로 계약한 것은 이상한 일이 아니다.
아래 설명에 따라 YDL 5를 PS3에 설치한다.
PS3 준비하기
리눅스를 설치하려면 여러 개의 추가 하드웨어가 필요하다.
- 디스플레이와 케이블링(cabling)
- USB 키보드
- USB 마우스
- USB 플래시 드라이브
디스플레이의 경우 몇 가지 문제점들이 있다. 우선, 20GB PS3에는 TV 같은 출력 장치에 부착되는 아날로그 복합 RCA 플러그만 있다. 이것을 특수 케이블을 통해서 VGA로 전환해야 한다. (참고자료) 헌데 아쉽게도, 이 케이블은 576x384 해상도로만 실행된다. 더 나은 해상도를 원한다면 HDMI 포트를 사용해야 한다. 하지만, 이렇게 해도 추가적인 문제들이 생긴다. HDMI는 케이블을 통해서 DVI로 쉽게 변환될 수 있다. 그렇다면, 이것은 DVI 호환 모니터로 피드(feed)될 수 있어야 하는 것이 맞지 않을까? 하지만 그렇지 않다. HDCP라고 하는 콘텐트 보호 프로토콜 때문에 HDMI 포트를 통해 데이터를 출력할 때, PS3는 어떤 데이터도 비 HDCP 호환 장치로 출력하지 않는다. 따라서, 여러분의 모니터가 HDCP 호환이라면, 이것을 사용해서는 PS3에서 디지털 출력을 할 수가 없고, 576x384 해상도로 고정된다. (컴포넌트 비디오 단자를 이용해 더 높은 해상도를 이뤄냈다는 보고도 있기는 하다.)
다음은 PLAYSTATION 3 준비 단계이다.
- 이더넷 케이블을 PS3에 연결한다. 네트워크에 DHCP 서버가 있는지를 확인한다.
- 만약 PS3를 처음 사용하는 것이라면, 첫 번째 부팅 시 프롬프트에 나타난 설정 단계를 따라서 PS3 시스템의 언어, 시간, 사용자 이름을 설정해야 한다.
-
Settings 다음 System
Settings로 가서 Format Utility를 선택한다.
-
Format Hard Disk를 선택하고 선택을 두 번 확인한다.
-
Custom 파티셔닝 스킴을 선택한다.
-
Allot 10GB to the Other OS를 선택한다. 이렇게 하면 PS3의 게임 OS를 위해 나머지 디스크 공간이 자동으로 확보된다. 완료되면 시스템을 재시작 한다.
- 시스템이 재시작 될 때, Settings 다음 System Update로 간다.
-
Update via Internet을 선택한다.
- 시스템 업데이트용 스크린을 따라서 최신 시스템 업데이트를 다운로드 및 설치한다. 일부 스크린에는 취소 버튼만 있고, 앞으로 가는 방법에 대한 지시가 없다. 앞으로 진행하려면 컨트롤러에서 X 버튼을 사용한다.
- PS3가 재시작 하면 리눅스를 설치할 준비가 된 것이다.
설치 준비하기
이제 리눅스를 준비할 차례이다. 다음은 (PS3가 아닌) 여러분의 컴퓨터에서 설치를 준비하는 과정이다.
- YDL 5 DVD ISO를 다운로드 하여 굽는다. CD 설치는 불가능 하다. PS3는 DVD만 가능하다.
- Sony에서 PS3 OtherOS 인스톨러를 다운로드하고(참고자료) otheros.self로 저장한다. 이것은 외부 부트로더를 설치하기 위해 PS3 게임 OS에서 실행되는 파일이다.
- Terra Soft에서 YDL 부트로더를 다운로드 하고(참고자료) otheros.bld로 저장한다. 이것은 Sony 인스톨러가 설치 할 부트로더가 될 것이다.
- USB 플래시 드라이브를 컴퓨터에 삽입한다.
- 플래시 드라이브의 탑 레벨에, PS3라는 디렉토리를 만든다. PS3 디렉토리 밑에 otheros라는 또 다른 디렉토리를 만든다.
- 여러분이 다운로드 했던 마지막 두 개의 파일들, otheros.self와 otheros.bld를 플래시 드라이브에 있는 PS3/otheros 디렉토리에 복사한다.
이제 설치 할 차례이다.
설치하기
다음 단계는 PS3에서 리눅스를 설치하는 단계이다.
- 컴퓨터에서 플래시 드라이브를 제거하고 이것을 PS3에 삽입한다.
-
Settings 다음 System Settings로 가서, Install Other OS를 선택한다.
- 인스톨러의 위치를 확인하고, 설치 프로세스 스크린을 따라간다. OS가 아닌 부트로더만 설치하는 것임을 명심하라.
- 인스톨러가 완료되면, Settings, 다음 System Settings로 가서 Default System을 선택한다. 그리고 나서, Other
OS를 선택하고 X 버튼을 누른다.
- YDL 5 DVD를 삽입한다.
- USB 키보드와 마우스를 연결한다.
- 시스템을 재시작 한다. 컨트롤러에 있는 PS 버튼을 누르고 Turn off the system을 선택하거나, 또는 5초 동안 파워 버튼을 누른다. 그런 다음 시스템을 다시 켠다.
- 다시 부팅될 때, 리눅스가 부팅되는 것처럼 보인다. 부트로더가 실제로 kboot라는 리눅스 커널을 스트리핑 하기 때문이다.
- kboot: 프롬프트로 가서, 출력이 HDMI 포트를 통해 나온다면
install을 입력하고, 아날로그로 할 것이라면installtext을 입력한다. 나머지 지시는 여러분이 installtext 옵션을 사용한 것으로 간주하지만, 별차이는 없다.
- 미디어 검사 후에, 스크린의 파란색 부분에 Traceback 에러가 생긴다. 이것을 무시하고 설치 스크린을 통해 진행한다.
- 파티셔닝에 대해 물으면, PS3 게임 OS를 제거하여 이를 무시한다. PS3의 Other OS 모드는 게스트 OS만 드라이브의 고유한 부분만 볼 수 있도록 한다. low-level 유틸리티는 드라이브의 다른 부분들을 볼 수 없다. 따라서 계속 진행하고 YDL이 드라이브 상의 모든 데이터를 지우고, 모든 파티션을 제거한 후 기본 레이아웃을 생성하도록 한다.
- 패키지 설치의 경우, 설치까지 약 한 시간이 걸린다. 하지만, DVD 전체를 설치하지는 않는다.
- 재부팅 될 때, 아날로그 출력을 사용한다면, kboot: 부트 프롬프트에
ydl480i를 타이핑 한다. 그렇지 않으면 아날로그 출력이 나타낼 수 없는 해상도로 출력이 될 것이다.
- 부팅될 때 설정 툴을 가져온다. 이 부분에서 여러분이 해야 할 것은 없다. 어떤 것도 하지 않는다면 타임아웃 되고 부팅 프로세스가 종료된다.
드디어 해냈다. YDL 5가 이제 여러분의 PS3에 설치되었다.
설치 후 설정
불행히도, 설치 프로그램은 모든 상세부분을 신경 쓰지 않는다. 아날로그 디스플레이는 특히 그렇다. 적절한 해상도로 자동 부팅하고, 아날로그 장치에 X Window System을 설정하며 Cell BE SDK를 설치하고 싶다면 여러 단계를 거쳐야 한다.
모든 명령들은 설치 DVD가 이러한 방식으로 마운트 되고, 여러분이 루트(root)로서 로그인 하는 것으로 간주한다.
아날로그 시스템이 시작 시 알맞은 해상도로 부팅되도록 하려면, /etc/kboot.conf 파일을 편집하고 default=ydl을 읽는 라인을 default=ydl480i로 수정하고 파일을 저장한다.
아날로그 장치용 X Window System을 설정하려면, 다음과 같이 Xautoconfig 패키지를 설치 및 실행해야 한다.
rpm -i /mnt/YellowDog/RPMS/Xautoconfig-*
Xautoconfig
|
이제 startx를 실행하여 X Window System을 시작한다. 아날로그 장치에서는 스크린이 매우 작다. 이 같은 작은 장치에서 도움이 될 만한 힌트가 있다. alt+left 마우스 버튼을 누르면 데스크탑으로 스크린을 드래그 할 수 있다. 타이틀 바를 볼 수 없을 경우에도 가능하다.
시스템 부팅 시 그래픽 로그인을 하도록 하려면 /etc/inittab 파일을 편집해야 한다. id:3:initdefault: 라인을 수정하여 id:5:initdefault:로 하고 파일을 저장한다. 시스템을 재부팅 할 때, 멋진 그래픽 로그인이 가능하다. 재부팅 후에 위에 나온 나머지 단계와 마찬가지로 DVD를 마운트 한다. Nautilus는 실제로 이를 다른 위치에서 마운트한다. 따라서, Nautilus를 사용하여 DVD를 마운트 한다면, /mnt 보다는 /media/CDROM에 마운트 될 것이다.
이제 Cell BE SDK V2.0을 설치할 차례이다. 인스톨러에 의해서 이미 설치되었는지를 보려면, which spu-gcc를 실행한다. 프로그램을 찾을 수 없다면 SDK가 설치되지 않은 것이다. 설치하려면 다음과 같이 한다.
cd /mnt/YellowDog/RPMS
rpm -i spu-binutils-* spu-gcc-* spu-gdb-* spu-utils* libspe-devel-*
|
하지만, 한 가지 중요한 패키지 세트가 DVD에 포함되지 않았다. 64-bit 버전의 libspe이다. 하지만, 쉽게 해결 할 수 있다. 소스 DVD나 웹 사이트에서 libspe의 SRPM을 가져온다. (libspe-1.1.0-1.src.rpm) 그리고 나서, 다운로드 했던 디렉토리로 가서 다음 단계를 수행한다.
rpm -i libspe-*.src.rpm
cd /usr/src/yellowdog/SPECS
rpmbuild -bb --target ppc64 libspe.spec
cd ../RPMS/ppc64
rpm -i elfspe-* libspe-*
|
드디어 YDL 5가 설치, 구성되어 실행할 준비가 되었다.
여러분 중에는 다시 게임 OS로 돌아가는 방법을 궁금해 하는 사람도 있을 것이다. 이렇게 하려면 kboot: 프롬프트나 명령행에서 boot-game-os를 실행한다. 어떤 이유로, 리눅스가 에러를 일으키거나 로딩되지 않으면, PS3 전원을 끄고 다시 전원이 켜졌을 때 5초 동안(진동음을 들을 때까지) 파워 버튼을 누른다. 이러한 방식으로 게임 OS를 로딩할 수 있지만, 기본 시스템이 게임 OS가 되도록 설정된다. 따라서, 리눅스로 부팅하려면, 그 설정으로 다시 가서 Other OS를 부팅하는 것으로 기본 설정을 해야 한다.
리눅스 설치 완료, 다음 단계는?
이제 리눅스와 Cell BE SDK가 설치되었으니, 이를 프로그래밍하고 사용하는 부분을 설명하겠다. 하지만, PPE와 SPE를 사용하는 C의 프로그램을 보도록 하자.
실행 방법을 보기 전에, Cell BE 프로그램을 구현하는데 사용되는 툴에 대해 알아보자.
-
gcc
PPE용 PPC 리눅스 바이너리를 생성하기 위해 구현된 믿을 수 있는 컴파일러이다. -m64 스위치를 사용하여 64-bit 실행 파일을 생성한다.
-
spu-gcc
이것 역시 믿을 수 있는 컴파일러이지만, SPE용 코드를 생성한다.
-
embedspu
SPE 프로그램을 PPE 실행 파일로 연결될 수 있는 객체 파일로 변환하는 특별한 툴이다. SPE 프로그램을 참조하는 글로벌 변수를 생성하여 PPE가 프로그램을 SPE로 로딩하고 필요할 때 프로그램을 실행할 수 있도록 한다. 64-bit PPC 프로그램으로 삽입하려면 -m64 플래그를 사용한다.
SPE 없이, Cell BE 프로세서는 다른 PowerPC 기반 시스템처럼 프로그래밍 된다. 사실, 이들이 존재하지 않고 여러분의 코드가 그저 잘 작동하는 것처럼 할 수도 있다. 하지만 이렇게 하면, 너무 많은 전력이 소모된다. SPE를 활용하려면, 더 많은 노력을 기울여야 한다.
Cell BE 기술이 생소하다면, PPE가 시스템용 리소스 매니저라는 것을 기억하라. 이것은 OS 태스크를 핸들하고, 메모리로의 액세스를 조정하고, SPE를 제어한다. PPE용 코드는 프로그램을 초기화 하고, 태스크를 가진 한 개 이상의 SPE를 설치하고, 입력과 출력을 수행한다. 물론, PPE 역시 프로세싱 태스크를 수행할 수 있지만, 중요한 것은 SPE에 맞는 것이 없다.
이제 간단한 프로그램이 구현되어 SPE에서 프로세싱 태스크가 어떻게 수행되는지를 보자. 프로그램은 매우 기본적이다. 주어진 속도(miles-per-hour)에서 여행한 거리를 계산한다. 다음은 PPE용 코드이다. (ppe_distance.c로 입력)
Listing 1. PPE 코드
#include <stdio.h>
#include <libspe.h>
//This global is for the SPE program code itself. It will be created by
//the embedspu program.
extern spe_program_handle_t calculate_distance_handle;
//This struct is used for input/output with the SPE task
typedef struct {
float speed; //input parameter
float num_hours; //input parameter
float distance; //output parameter
float padding; //pad the struct a multiple of 16 bytes
} program_data;
int main() {
program_data pd __attribute__((aligned(16))); //aligned for transfer
//GATHER DATA TO SEND TO SPE
printf("Enter the speed at which your car is travelling in miles/hr: ");
scanf("%f", &pd.speed);
printf("Enter the number of hours you have been driving at that speed: ");
scanf("%f", &pd.num_hours);
//USE THE SPE TO PROCESS THE DATA
//Create SPE Task
speid_t spe_id = spe_create_thread(0, &calculate_distance_handle, &pd, NULL,
-1, 0);
//Check For Errors
if(spe_id == 0) {
fprintf(stderr, "Error creating SPE thread!\n");
return 1;
}
//Wait For Completion
spe_wait(spe_id, NULL, 0);
//FORMAT THE RESULTS FOR DISPLAY
printf("The distance travelled is %f miles.\n", pd.distance);
return 0;
}
|
앞서 언급했던 것처럼, Cell BE 프로세서에서 PPE의 주요 역할은 입력과 출력 태스크를 다루는 것이다. 특히 흥미로운 부분은 spe_create_thread이다. 첫 번째 매개변수는 쓰레드 그룹 아이디(제로(0)는 이 쓰레드용 새로운 그룹을 만들어야 한다는 것을 나타낸다.), 두 번째 매개변수는 SPE 프로그램 핸들, 세 번째 매개변수는 전송하고자 하는 데이터에 대한 포인터, 네 번째 매개변수는 선택적인 환경 포인터, 다섯 번째 매개변수는 프로그램을 실행 할 SPE의 마스크(-1는 사용 가능한 SPE를 나타낸다.), 마지막 매개변수는 사용하고자 하는 옵션 리스트이다. (이 경우, 여러분은 어떤 것도 사용하지 않는다.) 함수는 SPE 태스크 아이디 넘버를 리턴하고, 여러분은 spe_wait에 대한 매개변수로서 사용한다. spe_wait은 SPE 태스크가 종료되면 리턴된다.
다음은 SPE용 코드이다. (spe_distance.c로서 입력함)
Listing 2. SPE 예제
//Pull in DMA commands
#include <spu_mfcio.h>
//Struct for communication with the PPE
typedef struct {
float speed; //input parameter
float num_hours; //input parameter
float distance; //output parameter
float padding; //pad the struct a multiple of 16 bytes
} program_data;
int main(unsigned long long spe_id, unsigned long long program_data_ea, unsigned
long long env) {
program_data pd __attribute__((aligned(16)));
int tag_id = 0;
//READ DATA IN
//Initiate copy
mfc_get(&pd, program_data_ea, sizeof(pd), tag_id, 0, 0);
//Wait for completion
mfc_write_tag_mask(1<<tag_id);
mfc_read_tag_status_any();
//PROCESS DATA
pd.distance = pd.speed * pd.num_hours;
//WRITE RESULTS OUT
//Initiate copy
mfc_put(&pd, program_data_ea, sizeof(program_data), tag_id, 0, 0);
//Wait for completion
mfc_write_tag_mask(1<<tag_id);
mfc_read_tag_status_any();
return 0;
}
|
향후 기술자료에서는 SPU 프로그램에 대해 보다 자세히 다루겠지만, 이 글에서 간단히 살펴보도록 하자. spe_create_thread에 대한 세 번째 매개변수로서 전달된 포인터는 이 프로그램에는 program_data_ea로서 나타난다. EA는 effective address를 의미하는데, 이것은 메인 PPE 프로그램에서 보여지는 메인 메모리 어드레스이다. SPE는 메인 메모리로의 직접적인 액세스를 할 수 없으므로, 이를 포인터로서 직접 참조할 수 없다. 대신, 트랜스퍼 요청을 실행하여 데이터를 로컬 스토어에 복사한다. 로컬 스토어에 복사되면, local store address(LSA)를 통해서 데이터에 액세스 할 수 있다.
mfc_get는 로컬 스토어로의 전송을 나타낸다. PPE와 SPE 모두, struct는 16바이트로 할당되고 16 바이트로 패딩된다. 향후 기술자료에서 이 부분을 자세히 다루겠지만, 대부분의 DMA 전송은 16-byte로 할당되고 16 bytes의 배수로 크기가 설정된다. tag_id를 사용하여 DMA 연산의 상태를 검색할 수 있다. 전송 후에, 다음 두 개의 함수들은 전송이 완료될 때까지 프로그램이 기다리도록 한다.
메인 프로세싱은 매우 단순하다. 속도와 시간을 곱하기만 하면 된다. 데이터가 처리된 후에, mfc_put은 전송을 메인 메모리로 초기화 하고 다음 두 개의 함수들은 DMA 완료를 기다리도록 한다. 모든 것이 끝나면 프로그램이 종료된다.
이제 여러분은 프로그램을 컴파일 하고 실행해야 한다. 매우 간단하다.
#Compile the SPE program
spu-gcc spe_distance.c -o spe_distance
#Embed the SPE program into an ELF object file, and expose it
#through the global variable: calculate_distance_handle
embedspu calculate_distance_handle spe_distance spe_distance_csf.o
#Compile the PPE program together with the SPE program
gcc ppe_distance.c spe_distance_csf.o -lspe -o distance
#Run the program
./distance
|
여러분이 드디어 해냈다. 완벽하게 작동하는 Cell BE 프로그램이 생겼다.
맺음말
PS3를 직접 프로그래밍 할 수 없지만, 서드 파티 OS 지원으로 인해 PS3에 리눅스를 설치할 수 있다. PS3에 리눅스를 설치하는 일은 어려운 일이지만, 궁극적으로 저렴하고 완벽하게 작동하는 Cell Broadband Engine 프로세서를 갖게 될 것이다. 본 시리즈에서 다룰 앞으로의 기술자료에서는 Cell BE 프로그래밍에 대해 자세히 설명하고 SPE의 속도를 최대한으로 높이는 부분을 설명할 것이다.
기사의 원문보기
참고자료
필자소개  | |  | Jonathan Bartlett은 리눅스 어셈블리 언어를 사용한 프로그래밍 개요서인 Programming from the Ground Up의 저자이다. New Medio의 책임 개발자이며, 웹, 비디오, 키오스크, 데스크탑 애플리케이션을 개발하고 있다. |
기사에 대한 평가
 |
| 이 문서 북마킹 하기
|
|  |