Catalog: parallelize all-sky tile prefetch
This commit is contained in:
1 parent
d9f2c83b9f
commit
457c0728b4
10 files changed
+371
-55
No files matched your search
+173
-25
@@ -6,6 +6,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <omp.h>
|
||||
|
||||
#define PI 3.14159265358979323846
|
||||
|
||||
enum {
|
||||
@@ -108,26 +110,40 @@ static size_t tile_index(int ra_index, int dec_index)
|
||||
return (size_t)dec_index * CATALOG_ALL_SKY_RA_TILES + ra_index;
|
||||
}
|
||||
|
||||
static int load_tile_file(const StarCatalog *catalog, int ra_index,
|
||||
int dec_index, Star **stars, size_t *count)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
int written;
|
||||
if (catalog == NULL || stars == NULL || count == NULL)
|
||||
return -1;
|
||||
*stars = NULL;
|
||||
*count = 0;
|
||||
written = snprintf(path, sizeof path, "%s/tile_ra%03d_dec%03d.csv",
|
||||
catalog->all_sky_root, ra_index, dec_index);
|
||||
if (written < 0 || (size_t)written >= sizeof path)
|
||||
return -1;
|
||||
StarCatalog temporary = {0};
|
||||
if (catalog_load_csv(&temporary, path))
|
||||
return -1;
|
||||
*stars = temporary.stars;
|
||||
*count = temporary.count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_tile(StarCatalog *catalog, int ra_index, int dec_index)
|
||||
{
|
||||
CatalogTile *tile = &catalog->tiles[tile_index(ra_index, dec_index)];
|
||||
char path[PATH_MAX];
|
||||
int written;
|
||||
Star *stars;
|
||||
size_t count;
|
||||
if (tile->state != 0)
|
||||
return tile->state == 1 ? 0 : -1;
|
||||
written = snprintf(path, sizeof path, "%s/tile_ra%03d_dec%03d.csv",
|
||||
catalog->all_sky_root, ra_index, dec_index);
|
||||
if (written < 0 || (size_t)written >= sizeof path) {
|
||||
if (load_tile_file(catalog, ra_index, dec_index, &stars, &count)) {
|
||||
tile->state = -1;
|
||||
return -1;
|
||||
}
|
||||
StarCatalog temporary = {0};
|
||||
if (catalog_load_csv(&temporary, path)) {
|
||||
tile->state = -1;
|
||||
return -1;
|
||||
}
|
||||
tile->stars = temporary.stars;
|
||||
tile->count = temporary.count;
|
||||
tile->stars = stars;
|
||||
tile->count = count;
|
||||
tile->state = 1;
|
||||
catalog->count += tile->count;
|
||||
return 0;
|
||||
@@ -255,15 +271,15 @@ static int tile_is_fully_contained(const double direction[3][3], int ra_index,
|
||||
return 1;
|
||||
}
|
||||
|
||||
int catalog_visit_source_triangle(StarCatalog *catalog,
|
||||
const double direction[3][3],
|
||||
int load_missing, CatalogTileVisitor visitor,
|
||||
void *context)
|
||||
typedef int (*CatalogTileIndexVisitor)(int ra_index, int dec_index,
|
||||
void *context);
|
||||
|
||||
static int visit_source_triangle_tile_indices(
|
||||
const double direction[3][3], CatalogTileIndexVisitor visitor,
|
||||
void *context)
|
||||
{
|
||||
if (catalog == NULL || direction == NULL || visitor == NULL)
|
||||
if (direction == NULL || visitor == NULL)
|
||||
return -1;
|
||||
if (catalog->kind == STAR_CATALOG_MEMORY)
|
||||
return visitor(catalog->stars, catalog->count, 0, context);
|
||||
double longitude[3], latitude[3], unwrapped[3];
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
lon_lat_from_direction(direction[i], &longitude[i], &latitude[i]);
|
||||
@@ -311,17 +327,149 @@ int catalog_visit_source_triangle(StarCatalog *catalog,
|
||||
for (int raw_ra = all_ra ? 0 : ra_first;
|
||||
raw_ra <= (all_ra ? 359 : ra_last); ++raw_ra) {
|
||||
const int ra = (raw_ra % 360 + 360) % 360;
|
||||
CatalogTile *tile = &catalog->tiles[tile_index(ra, dec)];
|
||||
if (load_missing && load_tile(catalog, ra, dec))
|
||||
continue; /* Downloader has not finished this tile yet. */
|
||||
if (tile->state != 1 ||
|
||||
visitor(tile->stars, tile->count,
|
||||
tile_is_fully_contained(direction, ra, dec), context))
|
||||
if (visitor(ra, dec, context))
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
StarCatalog *catalog;
|
||||
const double (*direction)[3];
|
||||
int load_missing;
|
||||
CatalogTileVisitor visitor;
|
||||
void *context;
|
||||
} CatalogVisitContext;
|
||||
|
||||
static int visit_catalog_tile(int ra_index, int dec_index, void *opaque)
|
||||
{
|
||||
CatalogVisitContext *context = opaque;
|
||||
CatalogTile *tile =
|
||||
&context->catalog->tiles[tile_index(ra_index, dec_index)];
|
||||
if (context->load_missing && load_tile(context->catalog, ra_index, dec_index))
|
||||
return 0; /* Downloader has not finished this tile yet. */
|
||||
if (tile->state != 1)
|
||||
return 0;
|
||||
return context->visitor(
|
||||
tile->stars, tile->count,
|
||||
tile_is_fully_contained(context->direction, ra_index, dec_index),
|
||||
context->context);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
unsigned char *requested;
|
||||
} CatalogMarkContext;
|
||||
|
||||
static int mark_catalog_tile(int ra_index, int dec_index, void *opaque)
|
||||
{
|
||||
CatalogMarkContext *context = opaque;
|
||||
context->requested[tile_index(ra_index, dec_index)] = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int catalog_mark_source_triangle_tiles(
|
||||
const double direction[3][3],
|
||||
unsigned char requested[CATALOG_ALL_SKY_TILE_COUNT])
|
||||
{
|
||||
CatalogMarkContext context = {.requested = requested};
|
||||
if (requested == NULL)
|
||||
return -1;
|
||||
return visit_source_triangle_tile_indices(direction, mark_catalog_tile,
|
||||
&context);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
size_t tile_id;
|
||||
Star *stars;
|
||||
size_t count;
|
||||
int loaded;
|
||||
} CatalogPendingTile;
|
||||
|
||||
int catalog_prefetch_marked_tiles(
|
||||
StarCatalog *catalog,
|
||||
const unsigned char requested[CATALOG_ALL_SKY_TILE_COUNT],
|
||||
int worker_count, CatalogPrefetchStats *stats)
|
||||
{
|
||||
CatalogPendingTile *pending = NULL;
|
||||
size_t pending_count = 0;
|
||||
double load_start;
|
||||
int result = -1;
|
||||
if (stats != NULL)
|
||||
*stats = (CatalogPrefetchStats){0};
|
||||
if (catalog == NULL || requested == NULL || worker_count <= 0)
|
||||
return -1;
|
||||
if (catalog->kind != STAR_CATALOG_ALL_SKY)
|
||||
return 0;
|
||||
for (size_t tile_id = 0; tile_id < CATALOG_ALL_SKY_TILE_COUNT; ++tile_id) {
|
||||
if (!requested[tile_id])
|
||||
continue;
|
||||
if (stats != NULL)
|
||||
++stats->requested_tiles;
|
||||
if (catalog->tiles[tile_id].state == 0)
|
||||
++pending_count;
|
||||
}
|
||||
if (pending_count == 0)
|
||||
return 0;
|
||||
pending = calloc(pending_count, sizeof *pending);
|
||||
if (pending == NULL)
|
||||
return -1;
|
||||
size_t pending_index = 0;
|
||||
for (size_t tile_id = 0; tile_id < CATALOG_ALL_SKY_TILE_COUNT; ++tile_id)
|
||||
if (requested[tile_id] && catalog->tiles[tile_id].state == 0)
|
||||
pending[pending_index++].tile_id = tile_id;
|
||||
if (worker_count > (int)pending_count)
|
||||
worker_count = (int)pending_count;
|
||||
load_start = omp_get_wtime();
|
||||
#pragma omp parallel for num_threads(worker_count) schedule(static)
|
||||
for (size_t i = 0; i < pending_count; ++i) {
|
||||
const int ra_index =
|
||||
(int)(pending[i].tile_id % CATALOG_ALL_SKY_RA_TILES);
|
||||
const int dec_index =
|
||||
(int)(pending[i].tile_id / CATALOG_ALL_SKY_RA_TILES);
|
||||
pending[i].loaded = !load_tile_file(
|
||||
catalog, ra_index, dec_index, &pending[i].stars, &pending[i].count);
|
||||
}
|
||||
if (stats != NULL)
|
||||
stats->load_seconds = omp_get_wtime() - load_start;
|
||||
/* Only this serial commit mutates the shared catalog cache. */
|
||||
for (size_t i = 0; i < pending_count; ++i) {
|
||||
CatalogTile *tile = &catalog->tiles[pending[i].tile_id];
|
||||
if (pending[i].loaded) {
|
||||
tile->stars = pending[i].stars;
|
||||
tile->count = pending[i].count;
|
||||
tile->state = 1;
|
||||
catalog->count += tile->count;
|
||||
if (stats != NULL) {
|
||||
++stats->newly_loaded_tiles;
|
||||
stats->newly_loaded_stars += tile->count;
|
||||
}
|
||||
} else {
|
||||
tile->state = -1;
|
||||
if (stats != NULL)
|
||||
++stats->unavailable_tiles;
|
||||
}
|
||||
}
|
||||
result = 0;
|
||||
free(pending);
|
||||
return result;
|
||||
}
|
||||
|
||||
int catalog_visit_source_triangle(StarCatalog *catalog,
|
||||
const double direction[3][3],
|
||||
int load_missing, CatalogTileVisitor visitor,
|
||||
void *context)
|
||||
{
|
||||
if (catalog == NULL || direction == NULL || visitor == NULL)
|
||||
return -1;
|
||||
if (catalog->kind == STAR_CATALOG_MEMORY)
|
||||
return visitor(catalog->stars, catalog->count, 0, context);
|
||||
CatalogVisitContext visit_context = {
|
||||
.catalog = catalog, .direction = direction, .load_missing = load_missing,
|
||||
.visitor = visitor, .context = context};
|
||||
return visit_source_triangle_tile_indices(direction, visit_catalog_tile,
|
||||
&visit_context);
|
||||
}
|
||||
|
||||
void catalog_destroy(StarCatalog *catalog)
|
||||
{
|
||||
if (catalog->tiles != NULL)
|
||||
|
||||
Reference in new issue
Block a user