LCOV - code coverage report
Current view: top level - src/dbm - dbm_shard.h (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:123285f) Lines: 100.0 % 15 15
Test Date: 2026-11-04 00:58:17 Functions: 100.0 % 2 2

            Line data    Source code
       1              : /*----------------------------------------------------------------------------*/
       2              : /*  CP2K: A general program to perform molecular dynamics simulations         */
       3              : /*  Copyright 2000-2026 CP2K developers group <https://cp2k.org>              */
       4              : /*                                                                            */
       5              : /*  SPDX-License-Identifier: BSD-3-Clause                                     */
       6              : /*----------------------------------------------------------------------------*/
       7              : #ifndef DBM_SHARD_H
       8              : #define DBM_SHARD_H
       9              : 
      10              : #include <omp.h>
      11              : 
      12              : #ifdef __cplusplus
      13              : extern "C" {
      14              : #endif
      15              : 
      16              : /*******************************************************************************
      17              :  * \brief Internal struct for storing a block's metadata.
      18              :  * \author Ole Schuett
      19              :  ******************************************************************************/
      20              : typedef struct {
      21              :   int row;
      22              :   int col;
      23              :   int offset;
      24              : } dbm_block_t;
      25              : 
      26              : /*******************************************************************************
      27              :  * \brief Internal struct for storing a matrix shard.
      28              :  * \author Ole Schuett
      29              :  ******************************************************************************/
      30              : typedef struct {
      31              :   int nblocks;
      32              :   int nblocks_allocated;
      33              :   dbm_block_t *blocks;
      34              : 
      35              :   int hashtable_size;  // should be a power of two
      36              :   int hashtable_prime; // should be a coprime of hashtable_size
      37              :   int *hashtable;      // maps row/col to block numbers
      38              : 
      39              :   int data_promised;  // ref'd by dbm_block_t.offset (not yet allocated)
      40              :   int data_allocated; // actually allocated (capacity of data buffer)
      41              :   int data_size;      // actually allocated and initialized
      42              :   double *data;       // potentially over-allocated (to amortize resizing)
      43              : 
      44              :   omp_lock_t lock; // used by dbm_put_block
      45              : } dbm_shard_t;
      46              : 
      47              : /*******************************************************************************
      48              :  * \brief Internal routine for initializing a shard.
      49              :  * \author Ole Schuett
      50              :  ******************************************************************************/
      51              : void dbm_shard_init(dbm_shard_t *shard);
      52              : 
      53              : /*******************************************************************************
      54              :  * \brief Internal routine for copying content of shard_b into shard_a.
      55              :  * \author Ole Schuett
      56              :  ******************************************************************************/
      57              : void dbm_shard_copy(dbm_shard_t *shard_a, const dbm_shard_t *shard_b);
      58              : 
      59              : /*******************************************************************************
      60              :  * \brief Internal routine for releasing a shard.
      61              :  * \author Ole Schuett
      62              :  ******************************************************************************/
      63              : void dbm_shard_release(dbm_shard_t *shard);
      64              : 
      65              : /*******************************************************************************
      66              :  * \brief Internal hash function based on Cantor pairing function.
      67              :  *        https://en.wikipedia.org/wiki/Pairing_function#Cantor_pairing_function
      68              :  *        Szudzik's elegant pairing proved to be too asymmetric wrt. row / col.
      69              :  *        Using unsigned int to return a positive number even after overflow.
      70              :  * \author Ole Schuett
      71              :  ******************************************************************************/
      72    247631271 : static inline unsigned int dbm_shard_hash(const unsigned int row,
      73              :                                           const unsigned int col) {
      74    247631271 :   return (row + col) * (row + col + 1) / 2 + row; // Division by 2 is cheap.
      75              : }
      76              : 
      77              : /*******************************************************************************
      78              :  * \brief Internal routine for the slot of a block in the shard's hashtable.
      79              :  * \author Hans Pabst
      80              :  ******************************************************************************/
      81    247631271 : static inline int dbm_shard_slot(const dbm_shard_t *shard, const int row,
      82              :                                  const int col) {
      83    247631271 :   return (shard->hashtable_prime * dbm_shard_hash(row, col)) &
      84    247631271 :          (shard->hashtable_size - 1);
      85              : }
      86              : 
      87              : /*******************************************************************************
      88              :  * \brief Internal routine for the slot following the given one (probing).
      89              :  * \author Hans Pabst
      90              :  ******************************************************************************/
      91      8960606 : static inline int dbm_shard_nextslot(const dbm_shard_t *shard, const int slot) {
      92      8960606 :   return (slot + 1) & (shard->hashtable_size - 1);
      93              : }
      94              : 
      95              : /*******************************************************************************
      96              :  * \brief Internal routines for prefetching an upcoming lookup in two stages:
      97              :  *        the hashtable slot first, then (once cached) the block it refers to.
      98              :  *        A lookup otherwise waits for two dependent cache misses.
      99              :  * \author Hans Pabst
     100              :  ******************************************************************************/
     101     17171355 : static inline void dbm_shard_prefetch_slot(const dbm_shard_t *shard,
     102              :                                            const int row, const int col) {
     103     17171355 :   __builtin_prefetch(&shard->hashtable[dbm_shard_slot(shard, row, col)]);
     104     17171355 : }
     105     23900902 : static inline void dbm_shard_prefetch_block(const dbm_shard_t *shard,
     106              :                                             const int row, const int col) {
     107     23900902 :   const int block_idx = shard->hashtable[dbm_shard_slot(shard, row, col)];
     108     23900902 :   if (0 < block_idx) { // first probe only, 1-based, 0 means empty
     109     19395732 :     __builtin_prefetch(&shard->blocks[block_idx - 1]);
     110              :   }
     111     23900902 : }
     112              : 
     113              : /*******************************************************************************
     114              :  * \brief Internal routine for looking up a block from a shard.
     115              :  * \author Ole Schuett
     116              :  ******************************************************************************/
     117              : dbm_block_t *dbm_shard_lookup(const dbm_shard_t *shard, const int row,
     118              :                               const int col);
     119              : 
     120              : /*******************************************************************************
     121              :  * \brief Internal routine for growing the block metadata of a shard such that
     122              :  *        it holds nblocks blocks in total without growing again.
     123              :  * \author Ole Schuett and Hans Pabst
     124              :  ******************************************************************************/
     125              : void dbm_shard_reserve(dbm_shard_t *shard, int nblocks);
     126              : 
     127              : /*******************************************************************************
     128              :  * \brief Internal routine for allocating the metadata of a new block.
     129              :  * \author Ole Schuett
     130              :  ******************************************************************************/
     131              : dbm_block_t *dbm_shard_promise_new_block(dbm_shard_t *shard, const int row,
     132              :                                          const int col, const int block_size);
     133              : 
     134              : /*******************************************************************************
     135              :  * \brief Internal routine for allocating and zeroing any promised block's data.
     136              :  * \author Ole Schuett
     137              :  ******************************************************************************/
     138              : void dbm_shard_allocate_promised_blocks(dbm_shard_t *shard);
     139              : 
     140              : /*******************************************************************************
     141              :  * \brief Internal routine for getting block or promising a new one.
     142              :  * \author Ole Schuett
     143              :  ******************************************************************************/
     144              : dbm_block_t *dbm_shard_get_or_promise_block(dbm_shard_t *shard, const int row,
     145              :                                             const int col,
     146              :                                             const int block_size);
     147              : 
     148              : /*******************************************************************************
     149              :  * \brief Internal routine for getting block or allocating a new one.
     150              :  * \author Ole Schuett
     151              :  ******************************************************************************/
     152              : dbm_block_t *dbm_shard_get_or_allocate_block(dbm_shard_t *shard, const int row,
     153              :                                              const int col,
     154              :                                              const int block_size);
     155              : 
     156              : #ifdef __cplusplus
     157              : }
     158              : #endif
     159              : 
     160              : #endif
     161              : 
     162              : // EOF
        

Generated by: LCOV version 2.0-1