Я попытался добавить #pragma parallel omp для этой программы трассировки лучей и измеряю одинаковое / очень похожее количество времени обработки с и без выражения pragma.
Это функция:
void Scene::SaveImage(
const char *outPngFileName,
int pixelsWide,
int pixelsHigh,
double zoom,
int antiAliasFactor) const
{
// Oversample the image using the anti-aliasing factor.
const int largePixelsWide = antiAliasFactor * pixelsWide;
const int largePixelsHigh = antiAliasFactor * pixelsHigh;
const int smallerDim =
((pixelsWide < pixelsHigh) ? pixelsWide : pixelsHigh);
const double largeZoom = antiAliasFactor * zoom * smallerDim;
ImageBuffer buffer(largePixelsWide, largePixelsHigh, backgroundColor);
// The camera is located at the origin.
Vector camera(0.0, 0.0, 0.0);
// The camera faces in the -z direction.
// This allows the +x direction to be to the right,
// and the +y direction to be upward.
Vector direction(0.0, 0.0, -1.0);
const Color fullIntensity(1.0, 1.0, 1.0);
// We keep a list of (i,j) screen coordinates for pixels
// we are not able to trace definitive rays for.
// Later we will come back and fix these pixels.
PixelList ambiguousPixelList;
#pragma omp parallel for
for (int i=0; i < largePixelsWide; ++i)
{
direction.x = (i - largePixelsWide/2.0) / largeZoom;
for (int j = 0; j < largePixelsHigh; ++j)
{
direction.y = (largePixelsHigh / 2.0 - j) / largeZoom;
#if RAYTRACE_DEBUG_POINTS
{
using namespace std;
// Assume no active debug point unless we find one below.
activeDebugPoint = NULL;
DebugPointList::const_iterator iter = debugPointList.begin();
DebugPointList::const_iterator end = debugPointList.end();
for(; iter != end; ++iter)
{
if ((iter->iPixel == i) && (iter->jPixel == j))
{
cout << endl;
cout << "Hit breakpoint at (";
cout << i << ", " << j <<")" << endl;
activeDebugPoint = &(*iter);
break;
}
}
}
#endif
PixelData& pixel = buffer.Pixel(i,j);
try
{
// Trace a ray from the camera toward the given direction
// to figure out what color to assign to this pixel.
pixel.color = TraceRay(
camera,
direction,
ambientRefraction,
fullIntensity,
0);
}
catch (AmbiguousIntersectionException)
{
// Getting here means that somewhere in the recursive
// code for tracing rays, there were multiple
// intersections that had minimum distance from a
// vantage point. This can be really bad,
// for example causing a ray of light to reflect
// inward into a solid.
// Mark the pixel as ambiguous, so that any other
// ambiguous pixels nearby know not to use it.
pixel.isAmbiguous = true;
// Keep a list of all ambiguous pixel coordinates
// so that we can rapidly enumerate through them
// in the disambiguation pass.
ambiguousPixelList.push_back(PixelCoordinates(i, j));
}
}
}
#if RAYTRACE_DEBUG_POINTS
// Leave no chance of a dangling pointer into debug points.
activeDebugPoint = NULL;
#endif
// Go back and "heal" ambiguous pixels as best we can.
PixelList::const_iterator iter = ambiguousPixelList.begin();
PixelList::const_iterator end = ambiguousPixelList.end();
for (; iter != end; ++iter)
{
const PixelCoordinates& p = *iter;
ResolveAmbiguousPixel(buffer, p.i, p.j);
}
// We want to scale the arbitrary range of
// color component values to the range 0..255
// allowed by PNG format. We therefore find
// the maximum red, green, or blue value anywhere
// in the image.
const double max = buffer.MaxColorValue();
// Downsample the image buffer to an integer array of RGBA
// values that LodePNG understands.
const unsigned char OPAQUE_ALPHA_VALUE = 255;
const unsigned BYTES_PER_PIXEL = 4;
// The number of bytes in buffer to be passed to LodePNG.
const unsigned RGBA_BUFFER_SIZE =
pixelsWide * pixelsHigh * BYTES_PER_PIXEL;
std::vector<unsigned char> rgbaBuffer(RGBA_BUFFER_SIZE);
unsigned rgbaIndex = 0;
const double patchSize = antiAliasFactor * antiAliasFactor;
//#pragma parallel for collapse(3)
for (int j=0; j < pixelsHigh; ++j)
{
for (int i=0; i < pixelsWide; ++i)
{
Color sum(0.0, 0.0, 0.0);
for (int di=0; di < antiAliasFactor; ++di)
{
//#pragma parallel omp for reduction(+:sum)
for (int dj=0; dj < antiAliasFactor; ++dj)
{
sum += buffer.Pixel(
antiAliasFactor*i + di,
antiAliasFactor*j + dj).color;
}
}
sum /= patchSize;
// Convert to integer red, green, blue, alpha values,
// all of which must be in the range 0..255.
rgbaBuffer[rgbaIndex++] = ConvertPixelValue(sum.red, max);
rgbaBuffer[rgbaIndex++] = ConvertPixelValue(sum.green, max);
rgbaBuffer[rgbaIndex++] = ConvertPixelValue(sum.blue, max);
rgbaBuffer[rgbaIndex++] = OPAQUE_ALPHA_VALUE;
}
}
// Write the PNG file
const unsigned error = lodepng::encode(
outPngFileName,
rgbaBuffer,
pixelsWide,
pixelsHigh);
// If there was an encoding error, throw an exception.
if (error != 0)
{
std::string message = "PNG encoder error: ";
message += lodepng_error_text(error);
throw ImagerException(message.c_str());
}
}
// The following function searches through all solid objects
// for the first solid (if any) that contains the given point.
// In the case of ties, the solid that was inserted into the
// scene first wins. This arbitrary convention allows the
// composer of a scene to decide which of multiple overlapping
// objects should control the index of refraction for any
// overlapping volumes of space.
const SolidObject* Scene::PrimaryContainer(const Vector& point) const
{
SolidObjectList::const_iterator iter = solidObjectList.begin();
SolidObjectList::const_iterator end = solidObjectList.end();
for (; iter != end; ++iter)
{
const SolidObject* solid = *iter;
if (solid->Contains(point))
{
return solid;
}
}
return NULL;
}
Это фрагмент, к которому я добавил его:
#pragma omp parallel for
for (int i=0; i < largePixelsWide; ++i)
{
direction.x = (i - largePixelsWide/2.0) / largeZoom;
for (int j = 0; j < largePixelsHigh; ++j)
{
direction.y = (largePixelsHigh / 2.0 - j) / largeZoom;
Я убедился, что все мои настройки VS17 верны, и -fopenmp main. cpp в аргументах команды. Дополнительная информация: это в другом файле с именем scene. cpp, заголовочный файл omp добавлен в scene. cpp.
Мои вопросы: как мне заставить это работать, и если есть другие части, где Я могу добавить это, где / как я бы go об этом. Спасибо.