2009-09-07 17 views
9

Estoy experimentando con OpenCL para aumentar la velocidad de nuestro software. Trabajamos mucho con mapas y, para simplificar, representamos un mapa como std :: vector < std :: vector>. La API de OpenCL toma punteros de estilo c en bruto como argumentos, por ejemplo, int * en el caso anterior.std :: arrays vectoriales y c-style

Mis preguntas:

  • ¿Existen garantías de ejecución en la que STL vector es, a nivel interno, consecutivas en la memoria?
  • ¿Puedo lanzar con seguridad un std :: vector a int * y esperar que funcione?
  • En el caso de un vector de vectores, ¿todavía puedo asumir que esto es cierto? Esperaría que el vector tuviera otros datos de estado, o problemas de alineación, o tal vez alguna otra cosa ...
  • ¿Cuál es la mejor manera de abordar esto? ¿Escribir una estructura de datos 2d personalizada que contenga un búfer interno en memoria contigua y trabajar con eso? Tendría que copiar mucho/a vectores mucho ...

Gracias.

+0

También le puede interesar esta pregunta: http://stackoverflow.com/questions/1339470/how-to-get-the-address-of-the-stdvector-buffer-start-most-elegantly –

+1

Tenga en cuenta que '' vector es una excepción a la regla http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=98 – Motti

Respuesta

17

¿Existen garantías de implementación en el stl que el vector es, internamente, consecutivo en la memoria?

A partir de C++ 03, sí, se garantiza que un vector utiliza el almacenamiento contiguo. (En C++ 98, hubo una laguna accidental por lo que una implementación podría usar hipotéticamente el almacenamiento no contiguo, pero se corrigió en la revisión de 2003 del estándar, y ninguna implementación en realidad usó el almacenamiento no contiguo porque ' d ser una idea terrible)

¿Puedo lanzar con seguridad un std :: vector a int * y espero que funcione?

La forma habitual es &v[0].(&*v.begin() probablemente también funcione, pero parece recordar que hay algunas palabras suaves en el estándar que hacen que esto no sea 100% confiable)

No. ¿Por qué esperas que funcione? Un vector es una clase. No es un puntero. Sólo contiene un puntero.

En el caso de un vector de vectores, ¿puedo seguir suponiendo que esto sea cierto? Esperaría que el vector tuviera otros datos de estado, o problemas de alineación, o tal vez alguna otra cosa ...

El vector se comporta igual en cualquier lugar que guarde en él. Si comete un vector de vectores, se termina con un objeto que contiene un puntero a una matriz de heap-asignado, donde cada elemento es un objeto que contiene un puntero a una matriz de heap-asignado.

En cuanto a cómo se debe abordar esto, depende de muchos factores. ¿Qué tan grande es su conjunto de datos total? Es posible que desee tener toda la tabla asignada contiguamente. Con un vector de vectores, cada fila es una asignación separada.

+0

Gracias. De hecho me formulé mi pregunta equivocada, me refería a 'primer elemento fundido a puntero' en lugar de 'vector fundido en sí', o 'dirección del vector mismo'.De todos modos, parece que no hay forma de trabajar fácilmente con los contenidos brutos de un vector de vectores, tendré que replantearme la forma en que trabajo con los datos. El tamaño típico es entre 500x500xsizeof (char sin signo) y 2500x2500xsizeof (double), y luego entre 20 y 50 de ellos, por lo que es bastante grande. – Roel

+0

Boost.MultiArray haría el trabajo por usted muy bien. Alternativamente, lo asignaría como una única matriz o vector contiguo lo suficientemente grande como para contener toda la tabla 2d – jalf

+1

Tenga en cuenta que 'vector ' es la excepción al caso de que '& v [0]' proporcione una matriz de estilo 'C' . – Motti

3

¿Existen garantías de implementación en el stl de que el vector es, internamente, consecutivo en la memoria?

Aunque no puedo citar los estándares aquí, he visto código en bibliotecas de alta calidad que asumen este diseño (a saber, POCO).

¿Puedo lanzar con seguridad un std :: vector a int * y espero que funcione?

Específicamente, no puede volver a montar el vector en sí. Sin embargo, he visto el siguiente código:

std::vector<int> vec; 
int* ptr = &vec[0]; 

En el caso de un vector de vectores, ¿puedo suponer que esto es cierto? Esperaría que el vector tuviera otros datos de estado, o problemas de alineación, o tal vez alguna otra cosa ...

Probablemente no se puede convertir un vector de vectores en una matriz lineal. Cada vector reservará su propio rango de memoria y no puede esperar que todos estos rangos sean secuenciales.

+1

no se puede emitir un iterador a un puntero @jalf – jalf

+0

: Gracias, te' estas en lo correcto. Confundí & vec [0] con (int *) vec.begin(). –

4
  • ¿Hay garantías de ejecución en la que STL vector es,
    internos, consecutivos en la memoria

Sí, es una matriz dinámica. Estándar garantiza que los objetos dentro del vector se almacenan consecutivamente.

  • ¿Puedo con seguridad emitir un std :: vector a int * y esperar que funcione?

No, pero se puede utilizar begin() y usar eso como el puntero.

  • ¿Hay garantías de ejecución en la STL que el vector es,
    internamente, consecutivos en la memoria

No, ya que el vector puede contener algunas variables miembro internos toda la matriz 2D no lo hará ser la ubicación de memoria continua

+1

"No, pero puede usar begin() y usarlo como puntero.", Eso no es verdad en general, y definitivamente no está garantizado por el estándar. Siempre debe tomar la dirección del iterador desreferenciado para obtener un puntero, por lo que "& * v.begin()" i.s.o. simplemente "v.begin()" – Pieter

2

usted ha mencionado en un comentario de que se trabaja con hasta 2500x2500xsizeof datos (dobles). En ese caso, sugeriría usar un único vector en lugar de un vector de vectores. Asigne elementos NxM en un vector y envuélvalo en una clase que exponga la indexación bidimensional si lo desea. Obtiene todos los beneficios del vector con una sobrecarga mínima y todos sus datos están todavía en la memoria contigua para un procesamiento rápido.

+0

Sí, este es probablemente el enfoque que deberíamos tomar, al menos en el contexto de esta pregunta. El problema es que nuestros tipos de datos 'mapas' también necesitan poder leer desde diferentes ubicaciones (en una red, desde el disco para mapas que son demasiado grandes para caber en la memoria (los mapas de 20 gigabytes no son una excepción), ... Solo tendrá que probar algunos enfoques o implementar varios y tener un mecanismo selector de tiempo de ejecución que determine el comportamiento óptimo en la máquina/conjunto de problemas del usuario. De todos modos, gracias por su comentario. – Roel