TTEntry* TranspositionTable::probe(const Key& key, bool& found) const { TTEntry* const tte = first_entry(key); for (int i = 0; i < ClusterSize; ++i) if (!tte[i].key64 || tte[i].key64 == key.p[1]) { if ((tte[i].genBound8 & 0xFC) != generation8 && tte[i].key64) tte[i].genBound8 = uint8_t(generation8 | tte[i].bound()); // Refresh return found = tte[i].key64 != 0, &tte[i]; } // Find an entry to be replaced according to the replacement strategy TTEntry* replace = tte; for (int i = 1; i < ClusterSize; ++i) // Due to our packed storage format for generation and its cyclic // nature we add 259 (256 is the modulus plus 3 to keep the lowest // two bound bits from affecting the result) to calculate the entry // age correctly even after generation8 overflows into the next cycle. if (replace->depth8 - ((259 + generation8 - replace->genBound8) & 0xFC) * 2 * OnePly > tte[i].depth8 - ((259 + generation8 - tte[i].genBound8) & 0xFC) * 2 * OnePly) replace = &tte[i]; return found = false, replace; }
TTEntry* TranspositionTable::probe(const Key key, uint32_t h, bool& found) const { TTEntry* const tte = first_entry(key); const uint16_t key16 = key >> 48; // Use the high 16 bits as key inside the cluster for (int i = 0; i < ClusterSize; ++i) if (!tte[i].key16 || (tte[i].key16 == key16 && tte[i].hand32 == h)) { if ((tte[i].genBound8 & 0xFC) != generation8 && tte[i].key16) tte[i].genBound8 = uint8_t(generation8 | tte[i].bound()); // Refresh return found = (bool)tte[i].key16, &tte[i]; } // Find an entry to be replaced according to the replacement strategy TTEntry* replace = tte; for (int i = 1; i < ClusterSize; ++i) // Due to our packed storage format for generation and its cyclic // nature we add 259 (256 is the modulus plus 3 to keep the lowest // two bound bits from affecting the result) to calculate the entry // age correctly even after generation8 overflows into the next cycle. if ( replace->depth8 - ((259 + generation8 - replace->genBound8) & 0xFC) * 2 * ONE_PLY > tte[i].depth8 - ((259 + generation8 - tte[i].genBound8) & 0xFC) * 2 * ONE_PLY) replace = &tte[i]; return found = false, replace; }
void TranspositionTable::store(const Key key, Value v, Bound b, Depth d, Move m, Value statV) { TTEntry *tte, *replace; uint32_t key32 = key >> 32; // Use the high 32 bits as key inside the cluster tte = replace = first_entry(key); for (unsigned i = 0; i < ClusterSize; ++i, ++tte) { if (!tte->key32 || tte->key32 == key32) // Empty or overwrite old { if (!m) m = tte->move(); // Preserve any existing ttMove replace = tte; break; } // Implement replace strategy if ( ( tte->generation8 == generation || tte->bound() == BOUND_EXACT) - (replace->generation8 == generation) - (tte->depth16 < replace->depth16) < 0) replace = tte; } replace->save(key32, v, b, d, m, generation, statV); }
void TranspositionTable::store(const Key key, Value v, Bound b, Depth d, Move m, Value statV, Value evalM) { int c1, c2, c3; TTEntry *tte, *replace; uint32_t key32 = key >> 32; // Use the high 32 bits as key inside the cluster tte = replace = first_entry(key); for (unsigned i = 0; i < ClusterSize; i++, tte++) { if (!tte->key() || tte->key() == key32) // Empty or overwrite old { if (!m) m = tte->move(); // Preserve any existing ttMove replace = tte; break; } // Implement replace strategy c1 = (replace->generation() == generation ? 2 : 0); c2 = (tte->generation() == generation || tte->bound() == BOUND_EXACT ? -2 : 0); c3 = (tte->depth() < replace->depth() ? 1 : 0); if (c1 + c2 + c3 > 0) replace = tte; } replace->save(key32, v, b, d, m, generation, statV, evalM); }
dl_dma_addr_t dl_dma_get_physical_segment(struct dl_dma_list* sl, void* address, unsigned long offset, unsigned long* length) { struct dl_dma_entry* e = first_entry(sl); unsigned long page_offset; unsigned long page_num; unsigned long page_oip; if (sl->dma_is_single) { if (length) *length = sl->size - offset; return (dl_dma_addr_t)e->dma_addr + offset; } page_offset = (unsigned long)address % PAGE_SIZE; page_num = (page_offset + offset) / PAGE_SIZE; page_oip = (page_offset + offset) % PAGE_SIZE; if (page_num > sl->num_pages) return 0; e = get_entry(e, page_num); if (length) *length = PAGE_SIZE - page_oip; return (dl_dma_addr_t)e->dma_addr + page_oip; }
struct dl_dma_list* dl_dma_map_user_buffer(void* page_array, unsigned long num_pages, int direction, void* pdev) { int i = 0; struct dl_dma_list* sl = NULL; struct dl_dma_entry *e = NULL; struct page** pages = (struct page**)page_array; if (!page_array) return NULL; sl = alloc_dl_dma_entry(num_pages); if (!sl) return NULL; e = first_entry(sl); direction = bmd_to_linux_direction(direction); for (i = 0; i < num_pages; i++) { e->dma_addr = pci_map_page(pdev, pages[i], 0, PAGE_SIZE, direction); e = next_entry(e); } sl->num_pages = num_pages; sl->pdev = pdev; return sl; }
void TranspositionTable::store(const Key posKey, Value v, ValueType t, Depth d, Move m, Value statV, Value kingD) { int c1, c2, c3; TTEntry *tte, *replace; uint32_t posKey32 = posKey >> 32; // Use the high 32 bits as key tte = replace = first_entry(posKey); for (int i = 0; i < ClusterSize; i++, tte++) { if (!tte->key() || tte->key() == posKey32) // empty or overwrite old { // Preserve any exsisting ttMove if (m == MOVE_NONE) m = tte->move(); tte->save(posKey32, v, t, d, m, generation, statV, kingD); return; } if (i == 0) // replace would be a no-op in this common case continue; c1 = (replace->generation() == generation ? 2 : 0); c2 = (tte->generation() == generation ? -2 : 0); c3 = (tte->depth() < replace->depth() ? 1 : 0); if (c1 + c2 + c3 > 0) replace = tte; } replace->save(posKey32, v, t, d, m, generation, statV, kingD); overwrites++; }
const TTEntry* TranspositionTable::probe(const Key key) const { const TTEntry* tte = first_entry(key); uint32_t key32 = key >> 32; for (unsigned i = 0; i < ClusterSize; i++, tte++) if (tte->key() == key32) return tte; return NULL; }
const TTEntry* TranspositionTable::probe(const Key key) const { TTEntry* tte = first_entry(key); uint32_t key32 = key >> 32; for (unsigned i = 0; i < ClusterSize; ++i, ++tte) if (tte->key32 == key32) { tte->generation8 = generation; // Refresh return tte; } return nullptr; }
void dl_dma_unmap_kernel_buffer(struct dl_dma_list* sl, int direction) { unsigned long i; struct dl_dma_entry *e = first_entry(sl); direction = bmd_to_linux_direction(direction); if (!sl->dma_is_single) { for (i = 0; i < sl->num_pages; i++) { pci_unmap_page(sl->pdev, e->dma_addr, PAGE_SIZE, direction); e = next_entry(e); } } else pci_unmap_single(sl->pdev, e->dma_addr, sl->size, direction); destroy_dl_dma_entry(sl); }
struct dl_dma_list* dl_dma_map_kernel_buffer(void *address, unsigned long size, int direction, int is_vmalloc, void* pdev) { struct page* page; int i = 0, offset = 0; struct dl_dma_list* sl = NULL; struct dl_dma_entry *e = NULL; unsigned long num_pages = dl_dma_get_num_pages(address, size); unsigned long start_addr = (unsigned long)address; start_addr = start_addr - (start_addr % PAGE_SIZE); sl = alloc_dl_dma_entry(is_vmalloc == 1 ? num_pages : 1); if (!sl) return NULL; e = first_entry(sl); direction = bmd_to_linux_direction(direction); if (is_vmalloc) { for (i = 0; i < num_pages; i++) { page = vmalloc_to_page((void*)(unsigned long)start_addr + offset); offset += PAGE_SIZE; e->dma_addr = pci_map_page(pdev, page, 0, PAGE_SIZE, direction); e = next_entry(e); } sl->num_pages = num_pages; } else { e->dma_addr = pci_map_single(pdev, address, size, direction); sl->dma_is_single = 1; sl->size = size; } sl->pdev = pdev; return sl; }
void TranspositionTable::store(const Key posKey, Value v, ValueType t, Depth d, Move16 m, Value statV, Value kingD) { #else void TranspositionTable::store(const Key posKey, Value v, ValueType t, Depth d, Move m, Value statV, Value kingD) { #endif int c1, c2, c3; TTEntry *tte, *replace; uint32_t posKey32 = posKey >> 32; // Use the high 32 bits as key inside the cluster tte = replace = first_entry(posKey); for (int i = 0; i < ClusterSize; i++, tte++) { if (!tte->key() || tte->key() == posKey32) // Empty or overwrite old { // Preserve any existing ttMove #ifdef GPSFISH if (m == MOVE16_NONE) m = tte->move16Val(); #else if (m == MOVE_NONE) m = tte->move(); #endif tte->save(posKey32, v, t, d, m, generation, statV, kingD); return; } // Implement replace strategy c1 = (replace->generation() == generation ? 2 : 0); c2 = (tte->generation() == generation || tte->type() == VALUE_TYPE_EXACT ? -2 : 0); c3 = (tte->depth() < replace->depth() ? 1 : 0); if (c1 + c2 + c3 > 0) replace = tte; } replace->save(posKey32, v, t, d, m, generation, statV, kingD); }
void ParsedName::List::count_dim (std::vector<int>& dim, size_t& current_entry, size_t current_dim) const { int n; bool stop = false; std::shared_ptr<const ParsedName> first_entry ( list[current_entry]); for (n = 0; current_entry < size(); n++) { for (size_t d = 0; d < current_dim; d++) if ( list[current_entry]->index (d) != first_entry->index (d)) stop = true; if (stop) break; if (current_dim < list[0]->ndim()-1) count_dim (dim, current_entry, current_dim+1); else current_entry++; } if (dim[current_dim] && dim[current_dim] != n) throw Exception ("number mismatch between number of images along different dimensions"); dim[current_dim] = n; }
TTEntry* TranspositionTable::probe(const Key key, bool& found) const { TTEntry* const tte = first_entry(key); const uint16_t key16 = key >> 48; // Use the high 16 bits as key inside the cluster for (int i = 0; i < ClusterSize; ++i) if (!tte[i].key16 || tte[i].key16 == key16) { if (tte[i].key16) tte[i].genBound8 = uint8_t(generation8 | tte[i].bound()); // Refresh return found = (bool)tte[i].key16, &tte[i]; } // Find an entry to be replaced according to the replacement strategy TTEntry* replace = tte; for (int i = 1; i < ClusterSize; ++i) if ( (( tte[i].genBound8 & 0xFC) == generation8 || tte[i].bound() == BOUND_EXACT) - ((replace->genBound8 & 0xFC) == generation8) - (tte[i].depth8 < replace->depth8) < 0) replace = &tte[i]; return found = false, replace; }
if (c1 + c2 + c3 > 0) replace = tte; } replace->save(posKey32, v, t, d, m, generation, statV, kingD); } /// TranspositionTable::probe() looks up the current position in the /// transposition table. Returns a pointer to the TTEntry or NULL if /// position is not found. TTEntry* TranspositionTable::probe(const Key posKey) const { uint32_t posKey32 = posKey >> 32; TTEntry* tte = first_entry(posKey); for (int i = 0; i < ClusterSize; i++, tte++) if (tte->key() == posKey32) return tte; return NULL; } /// TranspositionTable::new_search() is called at the beginning of every new /// search. It increments the "generation" variable, which is used to /// distinguish transposition table entries from previous searches from /// entries from the current search. void TranspositionTable::new_search() {
TTEntry* TranspositionTable::probe(const Key key, bool& found #if defined(USE_GLOBAL_OPTIONS) , size_t thread_id #endif ) const { ASSERT_LV3(clusterCount != 0); #if defined(USE_GLOBAL_OPTIONS) if (!GlobalOptions.use_hash_probe) { // 置換表にhitさせないモードであるなら、見つからなかったことにして // つねに確保しているメモリの先頭要素を返せば良い。(ここに書き込まれたところで問題ない) return found = false, first_entry(0); } #endif // 最初のTT_ENTRYのアドレス(このアドレスからTT_ENTRYがClusterSize分だけ連なっている) // keyの下位bitをいくつか使って、このアドレスを求めるので、自ずと下位bitはいくらかは一致していることになる。 TTEntry* tte; u8 gen8; #if !defined(USE_GLOBAL_OPTIONS) tte = first_entry(key); gen8 = generation(); #else if (GlobalOptions.use_per_thread_tt) { // スレッドごとに置換表の異なるエリアを渡す必要がある。 // 置換表にはclusterCount個のクラスターがあるのでこれをスレッドの個数で均等に割って、 // そのthread_id番目のblockを使わせてあげる、的な考え。 // // ただしkeyのbit0は手番bitであり、これはそのままindexのbit0に反映されている必要がある。 // // また、blockは2の倍数になるように下丸めしておく。 // ・上丸めするとblock*max_thread > clusterCountになりかねない) // ・2の倍数にしておかないと、(key % block)にkeyのbit0を反映させたときにこの値がblockと同じ値になる。 // (各スレッドが使えるのは、( 0~(block-1) ) + (thread_id * block)のTTEntryなので、これはまずい。 size_t block = (clusterCount / max_thread) & ~1; size_t index = (((size_t)key % block) & ~1 ) | ((size_t)key & 1); tte = &table[index + thread_id * block].entry[0]; } else { tte = first_entry(key); } gen8 = generation(thread_id); #endif // 上位16bitが合致するTT_ENTRYを探す const uint16_t key16 = key >> 48; // クラスターのなかから、keyが合致するTT_ENTRYを探す for (int i = 0; i < ClusterSize; ++i) { // returnする条件 // 1. 空のエントリーを見つけた(そこまではkeyが合致していないので、found==falseにして新規TT_ENTRYのアドレスとして返す) // 2. keyが合致しているentryを見つけた。(found==trueにしてそのTT_ENTRYのアドレスを返す) // Stockfishのコードだと、1.が成立したタイミングでもgenerationのrefreshをしているが、 // save()のときにgenerationを書き出すため、このケースにおいてrefreshは必要ない。 // 1. if (!tte[i].key16) return found = false, &tte[i]; // 2. if (tte[i].key16 == key16) { #if defined(USE_GLOBAL_OPTIONS) // 置換表とTTEntryの世代が異なるなら、信用できないと仮定するフラグ。 if (GlobalOptions.use_strict_generational_tt) if (tte[i].generation() != gen8) return found = false, &tte[i]; #endif tte[i].set_generation(gen8); // Refresh return found = true, &tte[i]; } } // 空きエントリーも、探していたkeyが格納されているentryが見当たらなかった。 // クラスター内のどれか一つを潰す必要がある。 TTEntry* replace = tte; for (int i = 1; i < ClusterSize; ++i) // ・深い探索の結果であるものほど価値があるので残しておきたい。depth8 × 重み1.0 // ・generationがいまの探索generationに近いものほど価値があるので残しておきたい。geration(4ずつ増える)×重み 2.0 // 以上に基いてスコアリングする。 // 以上の合計が一番小さいTTEntryを使う。 if (replace->depth8 - ((259 + gen8 - replace->genBound8) & 0xFC) * 2 > tte[i].depth8 - ((259 + gen8 - tte[i].genBound8) & 0xFC) * 2) replace = &tte[i]; // generationは256になるとオーバーフローして0になるのでそれをうまく処理できなければならない。 // a,bが8bitであるとき ( 256 + a - b ) & 0xff のようにすれば、オーバーフローを考慮した引き算が出来る。 // このテクニックを用いる。 // いま、 // a := generationは下位2bitは用いていないので0。 // b := genBound8は下位2bitにはBoundが入っているのでこれはゴミと考える。 // ( 256 + a - b + c) & 0xfc として c = 3としても結果に影響は及ぼさない、かつ、このゴミを無視した計算が出来る。 return found = false, replace; }