Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

235
Views
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 answers
Answer question

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!