2009-12-17 10 views
2

포인터 배열을 반복하고 각 항목에 대해 (MySQL 데이터베이스 또는 플랫 파일에서 가져온) 해당 데이터를 가져와야하는 PHP 함수를 작성했습니다. 잠재적으로 수천 및 수천 번의 반복이있을 수 있으므로이를 최적화하는 아이디어가 있습니까?PHP 루프 성능 최적화

첫 번째 생각은 내가 작업하는 캐시 된 데이터의 정적 배열을 갖는 것이었고 모든 수정은 캐시 된 배열을 변경 한 다음 디스크에 플러시 할 수있었습니다. 그러나 1000 개가 넘는 항목의 루프에서는 배열에 약 30 개만 유지하면 쓸모가 없습니다. 각 항목은 너무 크지 않지만 메모리에있는 1000 개 이상의 항목이 너무 많아서 디스크 저장 장치가 필요합니다.

데이터는 단지 gzipped 직렬화 된 개체입니다. 현재 데이터를 저장하는 데 데이터베이스를 사용하고 있지만 플랫 파일이 더 빠를 것이라고 생각합니다. (동시성 문제는 신경 쓰지 않고 구문 분석 할 필요가 없습니다. 압축을 풀고 병합하지 않아도됩니다.) 나는 이미 (DB 연결을 줄이기 위해) 5 개의 항목을 한꺼번에 가져 와서이 캐시에 저장하는 커스텀 반복자를 가지고있다. 그러나 다시 한번, 수천을 반복 할 필요가있을 때 30의 캐시를 사용하면 상당히 쓸모가 없습니다.

기본적으로 나는이 많은 항목을 신속하게 반복 할 수있는 방법이 필요합니다.

+0

나는 그래서 신경 세포가 그들의 데이터의 일부에 영향을 저장하는 객체 일부는 다음 중 하나에 갈 반복 할 필요가 신경 네트워크를 쓰고 있어요 ... 자신을 명확하게 설명하려고하여야을 memcached를하는 PHP API를가 등 1000+ 뉴런 나중에. 그런 다음 다시 역방향으로 반복해야합니다 (역 전파라고 함). 최상의 솔루션은 메모리와 IO 액세스 사이의 매체를 찾는 것이라고 생각합니다. 한 번에 100 개의 객체를로드하면 IO가 적지 만 메모리가 늘어납니다. – Louis

답변

1

글쎄, 아직 많이하지 않았다. 데이터를 설명하지 않고 데이터가 수행하는 작업이나 다른 개체와는 다른 개체가 필요한 상황, 개체가 일시적으로 해제되는 상황, 그리고 어떤 상황에서 다시 필요로하는지 등을 설명하지 않습니다.

아무도 아무 말도하지 않고 여기 어둠 속에서 완벽한 샷이 될 것입니다.

... 그 라인을 따라 가면 여기 어둠 속에서 촬영됩니다.

x 항목을 언제든지 메모리에 보관하는 것이 편리하면 x 항목에 대해 공간을 확보하십시오. 그런 다음 개체에 액세스 할 때마다 시간을 적어 두십시오 (시간에 따라 시계에 액세스하는 순서를 의미 할 수도 있음). 가장 최근에 사용한 항목이 목록에 더 빨리 나타나도록 각 항목을 목록에 유지합니다 (목록에 구현되지 않고 힙과 같은 구조로 구현 될 수 있음). 새 것을 메모리에 넣어야 할 때, 가장 오래 전에 사용 된 것을 교체 한 다음 해당 항목을 목록의 맨 앞으로 옮깁니다. 항목이 필요할 때 목록의 정확한 위치를 알 수 있도록 항목의 다른 색인을 유지해야 할 수도 있습니다. 그런 다음 항목이 위치한 곳을 찾아 부모와 자식 포인터를 적절히 연결 한 다음 목록의 맨 앞으로 이동합니다. 조회 시간을 최적화하는 다른 방법도있을 수 있습니다.

이것은 LRU 알고리즘이라고합니다. 가상 메모리를위한 페이지 대체 체계입니다. 그것이하는 것이 불가능할 때까지 병목 (디스크 I/O)을 지연시킵니다. 이 알고리즘이 최적의 교체를 보장하지는 않지만 그럼에도 불구하고 꽤 잘 수행된다는 점은 주목할 가치가 있습니다.

그 외에도 가능한 한 코드를 병렬 처리하여 하드 디스크에로드하거나 덤프해야하는 경우 하나의 항목을로드하거나 덤프해야 할 때 코드를 실제 작업을 수행하는 데 바쁘게 유지할 것을 권장합니다.

< 편집> 의견에 따라 신경망을 연구하고 있습니다. 수정 단계 이전에 데이터를 처음으로 채운 경우 (또는 수정 단계 이전에) 데이터를 적극적으로 사용하여 분류하는 경우 알고리즘을 잘못 구현하는 방법은 알 수 없습니다. 메모리에서 가장 일반적으로 사용되는 노드. 보정 단계에서

(아마도 백 소품?), 당신이 이미 방문했기 때문에 당신이 ... 메모리에 유지해야하는지 노드 자명하다! 네트워크가 큰 경우

, 당신은 멀리없이 디스크 I/O를 얻을하지 않을 수 있습니다. 트릭은 그것을 최소화하는 방법을 찾는 것입니다. </편집>

+0

죄송합니다. 설명하기가 어렵습니다. 데이터는 직렬화 된 객체이므로 직렬화를 해제하면 메모리에 저장됩니다. 그것이 제가 지금하고있는 일입니다. 그러나 문제는 내가 모든 것을 반복해야 할 때, 캐시에있는 것들이 마지막으로 사용될 것이므로 다른 함수가 새로운 반복을 시작할 때 캐시에있는 모든 것들이 끝날 때까지 필요하지 않을 때가있다. 기록을 위해, 나는 뉴런 네트워크에서 일하고 있습니다, 그러므로이 광기;) – Louis

+0

당신 말이 맞습니다. 문제는 훈련입니다. 하나의 레이어에서 뉴런을 반복하고 다음 등에서 뉴런을 반복하는 것을 의미하는 입력을 통해 네트워크 전달을 실행해야합니다. 그런 다음 최근에 실행 된 네트워크에서 오류를 계산하여 역방향으로 실행합니다. 나는 이것을 최적화하기 위해 열심히 노력하고 있으므로 하나의 반복 만 발생하지만 가능하지 않다고 생각합니다. 그렇습니다. 디스크 IO가 필요할 것입니다. 그러나 아마도 한 번에 많은 디스크를 가져 오는 것이 답입니다. 메모리는 결국 저렴합니다. – Louis

0

분명히 메모리에 저장하는 것이 다른 어떤 것보다 빠릅니다. 각 아이템은 얼마나 큰가요? 비록 그들이 각각 1K 일지라도, 그것의 만 개는 단지 10 개입니다.

+0

이미지가 비슷하거나 유사한 경우 압축 수준에 따라 수십 메가 이상의 주문이 표시 될 수 있습니다. 메모리에 15-meg 이미지 객체 100 개가있는 경우 1.5Gig 메모리를 사용했습니다. –

+0

각 항목은 아마도 약 1-5k이지만 100 명의 동시 사용자를 말하면 빠르게 높아집니다. – Louis

0

당신은 당신이 필요한 데이터를 얻은 후에 언제나 루프에서 탈출 할 수 있습니다. 그래서 루핑을 계속하지 않을 것입니다. 그것이 당신이 저장하는 플랫 파일이라면 .. 서버 HDD는 수천 또는 수백만 개의 다른 파일 크기를 가진 파일들을 포함하고 있습니다. 그러나 DB에 저장된 전체 실제 파일에 대해 이야기하고 있다면. 폴더에 저장하고 그 파일의 경로를 DB에 저장하는 것이 훨씬 낫습니다. 끌어온 항목을 XML에 넣어보십시오. 그래서 접근하기가 훨씬 쉬우 며 가져온 항목의 세부 사항 (이름, 업로드 한 날짜 등)에 대한 많은 속성을 포함 할 수 있습니다.

0

개체를 처음 읽을 때 memcached를 사용하여 개체를 저장 한 다음 이후 호출에서 캐시 된 버전을 사용할 수 있습니다. Memcached는 RAM을 사용하여 개체를 저장할 수 있으므로 메모리가 충분하면 오래 동안 사용할 수 있습니다.