Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

238
Vistas
Swift, matriz, procesamiento de imágenes. ¿Usar array.map() es la forma más rápida de procesar todos los datos en una matriz?

Tengo una matriz con muchos millones de elementos (puntos de datos de 7201 x 7201) donde convierto los datos en una imagen en escala de grises.

 var imagePixels = heights.map { terrainToColorScale($0.height, gradient: .Linear) } let _ = writeImageToFile(imagePixels, height: latStrides, width: lonStrides, imgColorSpace: .BW, to: imageURL, as: .png)

Este fragmento de código tarda unos 11 segundos en completarse (CPU = 2,3 Ghz 8-Core i9), pero me gustaría obtener un mejor rendimiento si es posible. El código se está ejecutando actualmente en un solo subproceso.

¿Simplemente dividir mi matriz de heights en fragmentos (digamos 100 fragmentos) y ejecutar un grupo de tareas con una tarea para cada fragmento obtendría una mejora decente? ¿O estoy buscando entrar en Metal y sombreadores (¡¡No sé nada sobre Metal!!) para obtener un mejor resultado?

Solo por interés, la imagen típica generada es... (Imagen reducida porque sería demasiado grande para cargarla aquí). Imagen en escala de grises de datos SRTM 1 arc-sec


Actualización: Adición de código asociado con terrainToColorScale Básicamente, para una conversión lineal, tomará la altura del terreno (típicamente 0...9000) y la escalará para devolver un valor entre 0...255 También tengo implementaciones no lineales (no se muestra a continuación) que mostrarán mayor detalle para los conjuntos de datos que son en su mayoría elevaciones de terreno bajas/altas.

 let terrainLowerCutOff: Double = 0.0 // Mean Sea Level let terrainUpperCutOff: Double = 9000.0 // Value in meters, just higher that Everest func terrainToColorScale(_ elev: Double, lowerCutOff: Double = terrainLowerCutOff, upperCutOff: Double = terrainUpperCutOff, gradient: ImageColorGradient = .Linear) -> UInt8 { switch gradient { case .Linear: return linearColorScale(elev, lowerCutOff: lowerCutOff, upperCutOff: upperCutOff) case .LinearInverse: return linearInverseColorScale(elev, lowerCutOff: lowerCutOff, upperCutOff: upperCutOff) case .CurveEmphasiseLows: return reciprocalPowerColorScale(elev, lowerCutOff: lowerCutOff, upperCutOff: upperCutOff) case .CurveEmphasiseLowsInverse: return reciprocalInversePowerColorScale(elev, lowerCutOff: lowerCutOff, upperCutOff: upperCutOff) case .CurveEmphasiseHighs: return powerColorScale(elev, lowerCutOff: lowerCutOff, upperCutOff: upperCutOff) case .CurveEmphasiseHighsInverse: return powerInverseColorScale(elev, lowerCutOff: lowerCutOff, upperCutOff: upperCutOff) } } fileprivate func linearColorScale(_ value: Double, lowerCutOff: Double, upperCutOff: Double) -> UInt8 { return UInt8( 255 * normaliseColorScale(value, lowerCutOff: lowerCutOff, upperCutOff: upperCutOff) ) } fileprivate func normaliseColorScale(_ value: Double, lowerCutOff: Double, upperCutOff: Double) -> Double { switch value { case _ where value <= lowerCutOff : return 0.0 case _ where value >= upperCutOff : return 1.0 default : return (value - lowerCutOff) / (upperCutOff - lowerCutOff) } }
over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Esta no es una respuesta completa a su pregunta, pero creo que debería darle un punto de partida sobre dónde ir. vDSP es parte de Accelerate y está diseñado para acelerar las operaciones matemáticas en arreglos. Este código usa varios pasos, por lo que probablemente podría optimizarse más, y no tiene en cuenta ningún otro filtro que no sea lineal, pero no tengo suficiente conocimiento para hacer que los pasos sean más efectivos. Sin embargo, en mi máquina, vDSP es 4 veces más rápido que map para el siguiente procesamiento:

 import Foundation import Accelerate let count = 7200 * 7200 var date = Date() print("Generating") let test: [CGPoint] = (0..<count).map { CGPoint(x: $0, y: Int.random(in: -2000...10000)) } print("Generating took \(Date().timeIntervalSince(date))") date = Date() print("Mapping") let heights: [Float] = test.map { Float($0.y) } print("Mapping took \(Date().timeIntervalSince(date))") date = Date() print("Converting via vDSP") let clipped = vDSP.clip(heights, to: 0...9000) let scaled = vDSP.divide(clipped, 9000) let multiplied = vDSP.multiply(255, scaled) let integers = vDSP.floatingPointToInteger(multiplied, integerType: UInt8.self, rounding: .towardNearestInteger) print("Converting via DSP took \(Date().timeIntervalSince(date))") date = Date() print("Converting via map") let mappedIntegers = heights.map { height -> UInt8 in let clipped: Float if height < 0 { clipped = 0 } else if height > 9000 { clipped = 9000 } else { clipped = height } let scaled = clipped / 9000 let multiplied = scaled * 255 return UInt8(multiplied.rounded()) } print("Converting via map took \(Date().timeIntervalSince(date))")
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda