...
This commit is contained in:
@@ -15,6 +15,7 @@ import kotlinx.coroutines.withTimeout
|
||||
import model.NewsItem
|
||||
import network.CorpInfo
|
||||
import network.RagService
|
||||
import util.HardwareDetector
|
||||
import java.net.URL
|
||||
import kotlin.random.Random
|
||||
|
||||
@@ -269,9 +270,20 @@ object DynamicNewsScraper {
|
||||
}
|
||||
|
||||
object SafeScraper {
|
||||
private val totalRam = HardwareDetector.getTotalRamGb()
|
||||
|
||||
// RAM 8GB당 1개 수준으로 설정하되, 최대 10~12개로 제한 (CPU 부하 방지)
|
||||
private val maxParallel = when {
|
||||
totalRam >= 128 -> 8
|
||||
totalRam >= 64 -> 6
|
||||
totalRam >= 32 -> 4
|
||||
totalRam >= 16 -> 2
|
||||
else -> 1
|
||||
}
|
||||
|
||||
// 동시 처리를 1개로 줄여서 안정성을 극대화 (추천)
|
||||
// Playwright는 여러 페이지를 띄울 때 CPU/메모리 점유율이 매우 높습니다.
|
||||
private val semaphore = Semaphore(2)
|
||||
private val semaphore = Semaphore(maxParallel)
|
||||
|
||||
suspend fun scrapeParallel(corpInfo: CorpInfo, urls: List<NewsItem>) = coroutineScope {
|
||||
urls.forEach { item -> // map + awaitAll 대신 순차 처리가 현재 상황에선 더 안정적입니다.
|
||||
|
||||
@@ -5,6 +5,7 @@ import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.launch
|
||||
import network.RagService
|
||||
import util.HardwareDetector
|
||||
import java.io.BufferedReader
|
||||
import java.io.File
|
||||
import java.io.InputStreamReader
|
||||
@@ -46,31 +47,48 @@ object LlamaServerManager {
|
||||
}
|
||||
}
|
||||
|
||||
fun startServer(binPath: String, modelPath: String, port: Int, nGpuLayers: Int = 99) {
|
||||
// 이미 해당 포트에서 실행 중이거나 모델 경로가 비었으면 무시합니다.
|
||||
fun startServer(binPath: String, modelPath: String, port: Int) {
|
||||
|
||||
if (processes.containsKey(port) || modelPath.isBlank()) return
|
||||
val os = System.getProperty("os.name").lowercase()
|
||||
val arch = System.getProperty("os.arch").lowercase()
|
||||
val isWin = os.contains("win")
|
||||
val (nGpuLayers, threads) = when {
|
||||
os.contains("mac") && (arch.contains("arm64") || arch.contains("aarch64")) -> 99 to 8
|
||||
isWin -> 4 to 12 // NUC Core Ultra 7: GPU 레이어 40 내외, 스레드 12 권장
|
||||
else -> 0 to 4 // 인텔 맥 2017 등
|
||||
}
|
||||
val isMacArm = os.contains("mac") && (arch.contains("arm64") || arch.contains("aarch64"))
|
||||
|
||||
val cpuCores = Runtime.getRuntime().availableProcessors() // HardwareDetector.getCpuCores()와 동일
|
||||
val hasGpu = HardwareDetector.hasNvidiaGpu()
|
||||
|
||||
// 1. optimalThreads: 할당 비율 적용 및 최소/최대 범위 제한(Safety Boundary)
|
||||
// 과도한 스레드 할당은 오히려 컨텍스트 스위칭 비용을 높여 성능을 저하시킬 수 있습니다.
|
||||
val ratio = if (isWin) 0.5 else 0.7
|
||||
val optimalThreads = (cpuCores * ratio).toInt().coerceIn(4, 16)
|
||||
|
||||
// 2. optimalGpuLayers: GPU 가속 조건 (윈도우 NVIDIA 또는 맥 ARM)
|
||||
val optimalGpuLayers = if ((isWin && hasGpu) || isMacArm) 99 else 4
|
||||
|
||||
println("🖥️ OS: $os / Arch: $arch")
|
||||
println("⚙️ 할당 스레드: $optimalThreads (Core: $cpuCores, Ratio: $ratio)")
|
||||
println("🚀 GPU 레이어: $optimalGpuLayers (NVIDIA/MacArm: ${if(optimalGpuLayers == 99) "YES" else "NO"})")
|
||||
|
||||
// val (nGpuLayers, threads) = when {
|
||||
// os.contains("mac") && (arch.contains("arm64") || arch.contains("aarch64")) -> 99 to 8
|
||||
// isWin -> optimalGpuLayers to optimalThreads // NUC Core Ultra 7: GPU 레이어 40 내외, 스레드 12 권장
|
||||
// else -> 0 to 4 // 인텔 맥 2017 등
|
||||
// }
|
||||
|
||||
val command = mutableListOf(
|
||||
binPath,
|
||||
"-m", modelPath,
|
||||
"--port", port.toString(),
|
||||
"-c", if (port == 8081) "512" else "8192",
|
||||
"-ngl", nGpuLayers.toString(),
|
||||
"-t", threads.toString(),
|
||||
"-ngl", optimalGpuLayers.toString(),
|
||||
"-t", optimalThreads.toString(),
|
||||
"--embedding"
|
||||
)
|
||||
if (port != 8081) { // 텍스트 생성용 모델에만 적용
|
||||
command.addAll(listOf(
|
||||
"-b", "512", // Batch size (토큰 병렬 처리량 제한으로 연산 안정화)
|
||||
"--threads-batch", threads.toString(),
|
||||
"--threads-batch", optimalThreads.toString(),
|
||||
"-fa","on" // Flash Attention 활성화 (메모리 절약 및 긴 컨텍스트 연산 안정성 증가)
|
||||
))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user