Abstract:
In a multi-processor (e.g., multi-core) computer system, several processors can simultaneously access data without corruption thereof by: designating to each processor a portion of a hash table containing the data; by allowing each processor to access only those data elements belonging to the portion of the hash table designated to that processor; and by sending, via a network, other data elements to the processors that are designated the portions of the hash table to which the other data elements belong. The network avoids memory contention at each processor without requiring a memory-based lock. This Abstract is provided for the sole purpose of complying with the Abstract requirement rules that allow a reader to quickly ascertain the subject matter of the disclosure contained herein. This Abstract is submitted with the explicit understanding that it will not be used to interpret or to limit the scope or the meaning of the claims.

Description:
CROSS REFERENCE TO RELATED APPLICATIONS 
     This application claims priority to and the benefit of U.S. provisional application Ser. No. 61/394,140, filed Oct. 18, 2010, disclosures of which is incorporated herein by reference in its entirety. 
    
    
     GOVERNMENT INTERESTS 
     This invention was made with Government support under contract no. FA8750-09-C-0229 awarded by the Air Force. The Government has certain rights in the invention. 
    
    
     FIELD OF THE INVENTION 
     The present invention generally relates to multi-core/processor systems, and in particular to systems in which two or more cores/processors concurrently process data. 
     BACKGROUND 
     In various computer applications, particularly those requiring processing of a large number of data elements (e.g., hundreds, thousands, or even millions of records), hash tables are typically used to store and/or access the data elements (collectively called data). In general, the hash tables provide faster, more efficient access to the data compared to storing/accessing the data using simple structures or arrays. The origins of hash tables date back to the 1960s, when authors of compilers used the concept of hashing as a mechanism for maintaining lists of user-defined names and associated properties. These initial developments lead to the formalization of several classic techniques used today to implement hash tables. These techniques include separate chaining, open addressing (linear, quadratic probing, double hashing), etc. 
     A hash table is usually implemented using a hash function, which receives a key, i.e., an attribute of the data element to be stored or accessed. The hash function generates an index (e.g., a number) into the hash table, the index corresponding to the key received. The data element is then stored in a “bucket” (e.g., a set of memory locations) identifiable by the index. The hash function may generate the same index for more than one key, each key corresponding to a different data element. As a result, more than one data element may be stored in one bucket. The time required to store a data element in a bucket, or to access the data element from a single bucket depends, in part, on the number of data elements in the bucket. In general, the more elements in the bucket, the more the storage and/or access time. 
     Typically, it is desirable to configure hash tables and hash functions such that the hash function generates, for several keys received, indices that are substantially uniformly distributed over the hash table. Therefore, each bucket may hold similar number of data elements. As a result, once a bucket corresponding to a data element is identified by the hash function, that data element can be stored in the identified bucket or accessed therefrom relatively efficiently compared to storing/accessing the data element from a bucket that contains significantly more elements than other buckets. 
     Various additional techniques such as bloom filters, d-left hashing, cache awareness, and lock-free algorithms have also been developed recently in order to improve the performance (e.g., access time, memory footprint, etc.) of the hash tables. Bloom filters, for example, can reduce the number of memory accesses of a hash table while locating a data element stored therein. Two-way chaining can reduce with high probability the size of the fullest bucket in a chaining-based hash table. By doing so, the maximum access time to the hash table is also reduced with high probability. The “always-go-left” algorithm may further improve the performance of two-way chaining technique by introducing asymmetry. The two-way chaining technique has been generalized as d-way chaining, and another hashing mechanism called d-left hashing was developed by combining d-way chaining and the always-go-left algorithm. 
     While the theoretic work on hash tables generally focuses on the algorithmic aspects of the problem (e.g., substantially even distribution of keys over the hash table), the specific details of the implementation of the hash table can play a crucial a role in determining the bottom-line performance of a computer system. One such important aspect of the implementation is the interaction between software and hardware resources and, specifically, the memory access patterns derived from stressing the hash table. To minimize expensive memory accesses, it is desirable that the system is designed or tuned to maximize cache hit ratios, which is an important system-performance parameter. 
     To this end, hash data structures that can fit in hardware cache lines have been proposed. For instance, in separate chaining (e.g., d-way chaining), hash tables can be tuned to have only a certain maximum number of collisions per entry (i.e., distinct keys that may be mapped by the hash function to the same bucket) that is less than or equal to the number of elements that fit into a cache line. If a bucket of the hash table to which a key is mapped is not located in the cache, one cache line may be accessed from the main memory, requiring one memory access. Because the bucket size is less than or equal to the size of the cache line, the entire bucket containing the required data element (or its designated memory location in the bucket) would now be available in the cache. As a result, hash-table operations such as put (i.e., store), get (i.e., access, read, etc.), and remove, may require only one memory access. The d-left hashing technique has been used to tune the maximum number of collisions per hash table entry in order to fit a bucket into a single cache line. The use of Bloom filters can avoid memory accesses for those get and remove operations invoked on elements that are not in the hash table. 
     Many modern computer systems include more than one processing units (e.g., processors, cores, etc.). In such systems, two processing units may simultaneously access a hash table or a location therein, and may seek to store or modify data at that location at the same time, which can cause data corruption. Two common hardware approaches to achieve concurrent access to a hash table while preventing data corruption include locking and using atomic operations such as compare and swap (CAS). 
     In locking, the entire hash table or small subcomponents thereof (e.g., buckets in a separate chaining-based table) are locked, i.e., when one processor is granted access to the hash table or a portion thereof, all other processors that may otherwise access the hash table are temporarily denied such access until the processor to which the access was granted completes its operation. Though locking may prevent data corruption, it can impose significant performance penalties on a system that includes several processors because each processor, before accessing a location in the hash table, must first determine whether that location is accessible at that time. The performance of systems employing locking can degrade even more as the number of processors or cores in the system increases because locking tends to scale poorly with large number of cores due to excessive amount of locking contention. 
     The CAS-based methods are sometimes also called “lock-free” methods, because they do not require locking a hash table or portions thereof. As one of ordinary skill in the art would appreciate, however, the CAS-based methods are, in fact, memory-based locking methods, requiring a lock to be maintained in the memory. Therefore, before accessing a location in the hash table, each processor/core in a multi-processor/core system must check the lock in the memory. As such, typical CAS-based methods still require some degree of memory contention, though that contention usually occurs at a table-entry level, rather than at a bucket or table level as is the case with lock-based methods. Though the check can be performed using a fast atomic operation such as CAS, the checking requirement can still impose performance penalties, and may limit scaling of the multi-core/processor system. 
     SUMMARY 
     In various provided embodiments, systems and methods for creating and/or operating a hash table called as a fast interconnect table (FIT) can facilitate concurrent access by a number of cores/processors of a multi-core/processor system to a FIT used by that system without requiring memory-based locking. This is achieved, in part, by partitioning the FIT on to the local memory units designated to each core such that a portion of the FIT to be processed by a certain core/processor is not located in the local memory unit of another core/processor. In addition, when a request to process a data element is received by a core not designated to process that data element, that data element is forwarded for processing to the appropriate core using a specialized network. Thus, both processing and synchronization of the data elements is achieved without requiring a memory-based lock. 
     Accordingly, in one aspect, a method is provided for allowing a processing element access to data. The method includes determining, at a first processing element (e.g., a core), if a datum is to be processed by the first processing element. This determination is based on a first function (e.g., a first hash function). If the datum is determined to be processed by the first processing element, the method includes selecting a table location based on the datum and a second function. The selected table location is designated to the first processing element. The method also includes accessing the datum at the selected table location. If the datum is determined not to be processed by the first processing element, the method includes communicating the datum to a second processing element, using a network configured to avoid contention for memory designated to the second processing element if the second processing element and any other processing element simultaneously access any data in the memory designated to the second processing element. 
     In some embodiments, the selected table location corresponds to memory designated to the first processing element. The memory designated to the first processing element may include a cache memory allocated to the first processing element and/or a main memory. Accessing the datum may include reading the datum, storing the datum, or both. 
     The second function may cause the selected table location to belong to a first bucket of memory locations within the memory designated to the first processing element. The second function may also cause a size of the first bucket to be less than or equal to a cache-line size of the memory. In some embodiments, the second processing element is designated to process the datum. Communicating the datum may include inserting the datum in a queue of data elements at the second processing element. Each element in the queue may access the memory designated to the second processing element in a sequence, so that contention for the memory may be avoided. 
     In some embodiments, the selected table location belongs to a first bucket of memory locations within a memory designated to the first processing element, and the method includes growing the first bucket of memory locations. The growing may include linking to the first bucket of memory locations a memory buffer having a size equal to the size of the first bucket. The growing may also include forming a second bucket of memory locations associated with the first bucket, and selecting a function to distribute data stored in the first bucket between the first and second buckets. In some embodiments the first and the second processing elements are located on a single chip. 
     In another aspect, a computing apparatus for accessing data includes a processor (e.g., a core in a multi-core system) and a memory coupled to the processor. The processor is configured to determine, based on a first function, if a datum is to be processed by the processor. If the datum is determined to be processed by the processor, the processor is configured to select a table location based on the datum and a second function, the selected table location being designated to the processor, and to access the datum at the selected table location. If the datum is determined not to be processed by the processor, the processor is configured to communicate the datum to another processor, using a network. The network is configured to avoid contention for memory designated to the second processor if the second processor and any other processor simultaneously access any data in the memory designated to the second processor. 
     The selected table location may correspond to the memory coupled to the processor. The memory coupled to the processor may include a cache memory allocated to the processor (e.g., L1 cache or L1 and L2 cache), and a main memory. The access includes reading the datum, storing the datum, or both. The processor and the other processor are located on a single chip. 
     In some embodiments the second function causes the selected table location to belong to a first bucket of memory locations within the memory coupled to the processor. The second function may also cause a size of the first bucket to be less than or equal to a cache-line size of the memory. 
     In some embodiments, the computing apparatus includes a network interface in communication with the network and the processor. The network interface is configured to create a queue of data elements, to receive a data element via the network, and to insert the received data element in the queue. This may cause each data element in the queue to accesses the memory coupled to the processor in a sequence, thereby avoiding contention for the memory. 
     In some embodiments, the selected table location belongs to a first bucket of memory locations within the memory coupled to the processor, and the processor is further configured to grow the first bucket of memory locations. The processor may be further configured to link to the first bucket of memory locations a memory buffer having a size equal to the size of the first bucket, thereby growing the first bucket. The processor may also be configured to form a second bucket of memory locations associated with the first bucket, and to select and execute a function to distribute data stored in the first bucket between the first and second buckets, thereby growing the first bucket. 
     In another aspect, an article of manufacture, including a non-transitory machine-readable medium storing instructions that, when executed by a first processing element, configure the first processing element to determine, based on a first function, if a datum is to be processed by the first processing element. If the datum is determined to be processed by the first processing element, the instructions configure the first processing element to select a table location based on the datum and a second function, the selected table location being designated to the first processing element, and to access the datum at the selected table location. If the datum is determined not to be processed by the first processing element, the instructions configure the first processing element to communicate the datum to a second processing element, using a network configured to avoid contention for memory designated to the second processing element if the second processing element and any other processing element simultaneously access any data in the memory designated to the second processing element. 
     The selected table location may correspond to memory designated to the first processing element. The memory designated to the first processing element may include a cache memory allocated to the first processing element, and a main memory. The second processing element may be designated to process the datum. Access to the datum may include reading the datum or storing the datum. The first and the second processing elements may be located on a single chip. 
     In some embodiments, the second function causes the selected table location to belong to a first bucket of memory locations within the memory designated to the first processing element. The second function may also cause a size of the first bucket to be less than or equal to a cache-line size of the memory. 
     In some embodiments, the instructions configure the second processing element to insert the datum in a queue of data elements at the second processing element. As such, each element in the queue may access the memory designated to the second processing element in a sequence, thereby avoiding contention for the memory. 
     The selected table location may belong to a first bucket of memory locations within a memory designated to the first processing element. The instruction may further configure the first processing element to grow the first bucket of memory locations. In some embodiments, the instruction further configure the first processing element to link to the first bucket of memory locations a memory buffer having a size equal to the size of the first bucket, thereby growing the first bucket. The instruction may also configure the first processing element to form a second bucket of memory locations associated with the first bucket, and to select a function to distribute data stored in the first bucket between the first and second buckets, thereby growing the first bucket. 
    
    
     
       BRIEF DESCRIPTION OF THE DRAWINGS 
       Various embodiments of the present invention taught herein are illustrated by way of example, and not by way of limitation, in the figures of the accompanying drawings, in which: 
         FIG. 1  illustrates a multi-core computer system employing a FIT, consistent with provided embodiments; 
         FIGS. 2 and 3  illustrate a multi-core computer system employing FITs that are grown, consistent with provided embodiments; 
         FIG. 4  illustrates a multi-core computer system including a memory system thereof, consistent with provided embodiments; and 
         FIGS. 5A and 5B  illustrate a network on a multi-core computer system, consistent with provided embodiments; 
     
    
    
     It will be recognized that some or all of the Figures are schematic representations for purposes of illustration and do not necessarily depict the actual relative sizes or locations of the elements shown. The Figures are provided for the purpose of illustrating one or more embodiments of the invention with the explicit understanding that they will not be used to limit the scope or the meaning of the claims. 
     DETAILED DESCRIPTION 
     In the following paragraphs, the present invention will be described in detail by way of example with reference to the attached drawings. While this invention is capable of embodiment in many different forms, there is shown in the drawings and will herein be described in detail specific embodiments, with the understanding that the present disclosure is to be considered as an example of the principles of the invention and not intended to limit the invention to the specific embodiments shown and described. That is, throughout this description, the embodiments and examples shown should be considered as exemplars, rather than as limitations on the present invention. Descriptions of well known components, methods and/or processing techniques are omitted so as to not unnecessarily obscure the invention. As used herein, the “present invention” refers to any one of the embodiments of the invention described herein, and any equivalents. Furthermore, reference to various feature(s) of the “present invention” throughout this document does not mean that all claimed embodiments or methods must include the referenced feature(s). 
     The following notation will be used to describe the lock-free multi-core (LFM) algorithm: 
     
       
         
               
               
             
           
               
                   
               
               
                 Term 
                 Definition 
               
               
                   
               
             
             
               
                 N 
                 The number of cores available to process hash 
               
               
                   
                 table operations 
               
               
                 H M   
                 A hash function that returns an integer value  
               
               
                   
                 between 0 and M 
               
               
                 L 
                 The number of entries that can fit into a cache line 
               
               
                 T 
                 A hash table 
               
               
                 B 
                 Number of buckets in the hash table 
               
               
                 T[b] 
                 (b + 1)-th bucket in hash table T 
               
               
                 forwardCore(c, m) 
                 A function that forwards a message m to core c 
               
               
                 thisCoreId( ) 
                 A function that returns the identifier of the core on  
               
               
                   
                 which it is invoked 
               
               
                   
               
             
          
         
       
     
     The nominal load factor (NLF) is defined as the number of stored keys divided by the number of buckets, i.e., 
     
       
         
           
             
               N 
               ⁢ 
               
                   
               
               ⁢ 
               L 
               ⁢ 
               
                   
               
               ⁢ 
               F 
             
             = 
             
               
                 number 
                 ⁢ 
                 
                     
                 
                 ⁢ 
                 of 
                 ⁢ 
                 
                     
                 
                 ⁢ 
                 stored 
                 ⁢ 
                 
                     
                 
                 ⁢ 
                 keys 
               
               
                 number 
                 ⁢ 
                 
                     
                 
                 ⁢ 
                 of 
                 ⁢ 
                 
                     
                 
                 ⁢ 
                 buckets 
               
             
           
         
       
     
     The effective load factor (ELF) is defined as the number of stored keys divided by the number of buckets times the number of entries per bucket, i.e., 
     
       
         
           
             
               N 
               ⁢ 
               
                   
               
               ⁢ 
               L 
               ⁢ 
               
                   
               
               ⁢ 
               F 
             
             = 
             
               
                 number 
                 ⁢ 
                 
                     
                 
                 ⁢ 
                 of 
                 ⁢ 
                 
                     
                 
                 ⁢ 
                 stored 
                 ⁢ 
                 
                     
                 
                 ⁢ 
                 keys 
               
               
                 number 
                 ⁢ 
                 
                     
                 
                 ⁢ 
                 of 
                 ⁢ 
                 
                     
                 
                 ⁢ 
                 buckets 
                 × 
                 number 
                 ⁢ 
                 
                     
                 
                 ⁢ 
                 of 
                 ⁢ 
                 
                     
                 
                 ⁢ 
                 entries 
                 ⁢ 
                 
                     
                 
                 ⁢ 
                 per 
                 ⁢ 
                 
                     
                 
                 ⁢ 
                 bucket 
               
             
           
         
       
     
     The nominal load factor can provide an estimate of the number of collisions produced in a hash table operation. On the other hand, for the case in which buckets are tuned to be of size equal to L (i.e., the size of a cache line), the effective load factor can provide an estimate of the number of memory accesses required by a hash table operation. This is because the underlying hardware executes memory reads by loading into the cache memory segments of size equal to the cache line size (i.e., L). Therefore, when the size of the bucket is less than or equal to L, only one memory access may be required to load a complete bucket, that contains the required data element, into the cache. 
     The value of NLF does not depend on the underlying hardware (i.e., it is hardware agnostic), but the ELF provides hardware-awareness because the value of ELF depends on L, i.e., the size of the cache line. Various embodiments of the LFM-based systems and methods described herein, rather than merely minimizing the value of the nominal load factor, adjust or optimize the value of ELF, thereby using information about the underlying hardware to improve the performance thereof. 
     The LFM algorithm initiates by allocating a hash table with p×N buckets, for some integer p, that, for example can be the number of buckets per core. Upon receiving a key k (i.e., a value of a data element to be processed) at an arbitrary core C of a multi-core system, the operations to process that key k are described in the following algorithm:
         h←H N (k);   if h==thisCoreId( )
           h′←H′(k);   processKey(T[h′], k);   
           else
           forwardCore(h, k);   
           endif The algorithm uses a first hash function H N (k) to decide which core of the multi-core system must process the key k. If H N (k) returns a coreid h that is different than the identifier of the core C at which this processing is being performed, the key k is forwarded to the core h designated to process the key k. Otherwise, the core C calculates a new hash value h′ using another hash function H′(k) and uses a bucket T[h] to process the key k.       

     Thus, the LFM algorithm employs two hash functions. First, it uses H N (k) to determine which core will process a processing request with respect the key k. Then, the LFM algorithm uses the second hash function H′(k) to retrieve a bucket in the hash table assigned to the key k. Various hash functions can be selected as the first and second hash functions, thereby inducing a family of LFM algorithms that can provide a degree of flexibility in designing hash tables that are cache aware. 
     In general, a multi-core/processor system includes several cache memory units and a main memory. Each processor/core is typically designated a cache memory unit, while the main memory is common to some or all processors/cores. Generally, a cache memory unit designated to a processor/core can be directly accessed by that processor/core, but a cache memory unit designated to another processor/core may only be accessed via the other processor/core. As such, a direct access to a processor&#39;s own cache tends to be substantially faster than an indirect access to another processor&#39;s or core&#39;s cache via that processor/core. A cache memory unit may include various levels of cache, usually designated as L1 cache, L2 cache, etc. 
     One family of hash functions, denoted as {H N , H′} provides L1 cache awareness. The hash functions family {H N , H′} is L1-cache aware if the following property is satisfied by the hash functions:
         (1) Let k and k′ be two different keys, then:
           If H N (k)≠H N (k′) implies H′(k)≠H′(k′)   
           (2) U {H′(k), for all possible key k}={1, . . . , B}, where B is the current number of buckets in the table       

     The first condition ensures that every bucket can only be accessed by one processor/core. In a multi-processor/core system, this property can configure the cores such that a core will not try to fetch buckets that are cached (i.e., located) in some other core&#39;s cache. Accordingly, this condition may eliminate or mitigate cache misses produced in typical multi-processor/core environments where different cores compete against each other for the cache memory resources. Due to this property, a portion of the hash table Tc that is designated to be accessed by a core C is located in the L1 cache of the core C, and the other portions of the hast table, i.e. (T-Tc), are not located in the L1 cache of the core C. 
     As described above, the core C can directly, and hence, rapidly access the data elements in its own L1 cache. Therefore, according to this configuration, each processor/core in the multi-core/processor system can access the data elements in the portion of the hash table to be processed by that core/processor. This can make each core “very good” (i.e., efficient) at processing the portion of the hash table designated to that core. 
     In this configuration, although a processor/core m cannot efficiently access a portion of the hash table (T-Tm), because that portion is not located in the L1 cache of the processor/core m, the core m does not specialize (i.e., it is not designated) the data elements that belong to the (T-Tm) portion of the hash table, and hence, the core m would not be required to access the (T-Tm) portion of the hash table. Because the hash functions are responsible to assign a key k to that core that has specialized in the portion of the table storing the key k, by choosing a family of hash function {H N , H′} satisfying the L1-cache awareness conditions (i.e., the conditions 1 and 2, described above), separation of concerns can be provided. According to the separation of concerns, a core/processor may be required to access data only from its own cache, or from the main memory, and not from the cache of another core/processor. 
     The above-described property that provides of L1-cache aware family of hash functions also results in the following two lemmas.
         Lemma 1. The set of buckets Bc assigned to core c is given by:
           Bc={b such that H N (b)=c}   
           Lemma 2. The pair of hash functions {H N , H′=H B } satisfy the L1-cache awareness property for B=p×N, where p is an integer, e.g., representing the number of buckets per core/processor.       

     With reference to  FIG. 1 , in an embodiment of a FIT based on the LFM algorithm in which N=2 and L=4, the initial set of hash functions is chosen as {H 2 , H 2 }, where H 2 (k)=k mod 2. According to Lemma 2, such hash functions satisfy the L1-cache awareness property. For example, consider a set of keys equal to the set of natural numbers {0, 1, 2, 3, . . . }. For key k=4, H 2 (4)=0, therefore the key 4 is forwarded to core C0. Then, core C0 will use a bucket identified by H 2 (4)=0, i.e., bucket B0, to process the key 4. For another key k=5, because H 2 (5)=1, the key 5 will be designated to core C1, which will use bucket B1 to process the key 5. In general, keys {0, 2, 4, 6} will be stored in the bucket B0, while keys {1, 3, 5, 7} will reside in the bucket B1. For this initial set up, the hash table has NLF=4 and ELF=1. 
     If the number of elements in a bucket is allowed to grow beyond L, a grow algorithm is required to increase the size of the hash table. For example, suppose that the bucket B1 becomes full with 4 entries {1, 3, 5, 7}. Upon arrival of the next key k=9, in order to store that key (or the data element associated with the key 9), the hash table must be grown. The table may be grown in two ways: (1) bucket enlargement, or (2) bucket spawning. 
     With reference to  FIG. 2 , bucket enlargement allocates a new buffer of memory to store L more elements, and links the buffer to the bucket it intends to enlarge. According to the example above, the bucket B1 is increased with an additional memory segment S, making the size of the bucket B1 equal to 8 elements. Under this approach both the nominal and effective load factors can increase. For example, growing the bucket B1 causes NLF=6 and ELF=1.5, both becoming 50% larger than their respective original values. 
     The bucket spawning algorithm creates a new bucket instead of enlarging an existing one, and can thus provide a mechanism to grow the hash table without causing the NLF and ELF to increase. With reference to  FIG. 3 , upon arrival of key k=9, the following actions take place:
         Bucket allocation: a new bucket of size L elements is allocated; its bucket identifier is set to 3, i.e., the new bucket is denoted as B3.       

     Update hash function: the hash function in core C1 is changed from H 2  to H 4 , where H 4 (k)=k mod 4.
         Move elements: the elements in bucket B1 are removed and reinserted using the new hash function H 4 .   Insert new key: the new key k=9 is now inserted using the new hash function H 4 .       

     In the example above, the new key k=9 is inserted in bucket B1, but in some instances, the new key may be inserted in the new bucket. In this example, the NLF remains equal to 4 and the ELF remains equal to 1. Furthermore, because all operations in spawning a bucket (i.e., allocation, rehashing, moving, inserting) can be made by one single process, there is no need for providing a memory lock. As such, bucket spawning facilitates the memory lock-free mechanism for growing a hash table that may be concurrently accessed by a number of processors/cores. 
     One overhead incurred by bucket spawning is that some elements may need to be moved from the existing buckets to the newly created buckets. For instance, in the example above, the element corresponding to key k=3 must be moved from the bucket B1 to the bucket B3 because the hash function was changed from H 2  to H 4 . Such operation is necessary so as to keep the load factors unchanged. However under certain conditions, for example, if the number of buckets is a power of 2, on an average only half of the elements in the previously allocated buckets need to be moved to the new buckets due to the split-order property of those buckets. 
     Various embodiments of high performance hash tables that are tuned according to the specific nature of the application and the underlying set of hardware resources, as described above, can be further improved. Consider, for example, a Bloom filter that may take into account the nature of the application. Let h be the probability that a get(k) request for a key k on a hash table T returns a value equal to NULL. Then, there exists a value h t  such that if h&gt;h t , then the average time to resolve a get(k) request (a request that provides access to a data element corresponding to the key k) can be reduced by implementing a Bloom filter to first check membership of k in T. If the Bloom filter returns FALSE, then immediately return NULL to the caller (i.e., a module requesting the data element corresponding to the key k) without looking up the hash table. Otherwise, look up the hash table for key k. 
     In this example, the Bloom filter acts as a fast path implementation. If the fast path returns FALSE, then there is no need to execute the slow path (i.e., the actual look up operation on the hash table T of the key k). The probability that the fast path returns FALSE is close but not larger than h. This probability may not be exactly equal to h because Bloom filters may generate false positives. 
     Alternatively, or in addition, consider the d-left algorithm that can account for the nature of the hardware, and thus, provides a mechanism to control the load factors NLF and ELF. By increasing the d value, i.e., the number of hash functions used in a d-left hashing, the maximum number of elements in a bucket can be decreased. In general, when there are as many elements as buckets, the size of the bucket depends on d as follows: 
                       log   ⁡     (     log   ⁡     (   n   )       )         log   ⁡     (   d   )         +   O           (   1   )               
where n is the number of elements in the table. As the number of hash functions d increases, the bucket size decreases, and hence, d can be used as a tuning parameter for the design of buckets that may fit into cache lines. Therefore, for a given cache line size L that is determined by the underlying hardware architecture, the d parameter can be selected to yield buckets of size less than or equal to L.
 
     To provide a flexible implementation that can accommodate for a variety of application and hardware environments, various building blocks that can be coupled with embodiments of the LFM algorithm, depending on the requirements of the problem, are provided. These building blocks include linked list-based buckets, vector based buckets, separate chaining hashing scheme, open addressing hashing scheme, hash tables, sets, Bloom filters to optimize membership checking in the hash table, d-left hashing to tune optimize the number of collisions, LFM algorithm, and CoreNetworks. 
     With reference to  FIG. 4 , Tilera, a multi-core system  400  includes an on-chip caching subsystem  402 . Although only a data cache subsystem  402  is described herein, various embodiments may include the instruction cache subsystem, either individually or in combination with the data cache subsystem  402 . A core  404   a  is coupled with its own L1 cache  406   a  and L2 cache  408   a . An L1 cache  406   a  may be exclusively used by the core  404   a  that owns it, while the L2 cache  408   a  can be remotely accessed from foreign cores, e.g., the cores  404   b ,  404   c ,  404   k , at a performance penalty. If data required by the core  404   a  cannot be located in either of its caches  406   a ,  408   a , then the data is fetched from an off-chip main memory  410 . 
     The following Table summarizes the access times to each of the storage subcomponents of Tilera. Of special interest is the latency incurred to perform an L2 remote access operation, which at 30 to 60 cycles, is 3 to 7 times slower than a local access to L2 cache. Various embodiments of the concurrently accessible FIT can avoid the need to perform such types of accesses, because, as described above, each core  404   a ,  404   b ,  404   c ,  404   k  is configured to specialize on non-overlapping segments of the hash table. For any core, the corresponding segment is not located on the cache of another core. 
     
       
         
               
               
               
             
           
               
                   
                   
               
               
                   
                 Operation 
                 Latency 
               
               
                   
                   
               
             
             
               
                   
                 L1 cache access (always local) 
                 2 cycles 
               
               
                   
                 L2 local cache access 
                 8 cycles 
               
               
                   
                 L2 remote access 
                 30-60 cycles 
               
               
                   
                 Memory access 
                 80 cycles 
               
               
                   
                   
               
             
          
         
       
     
     With reference to  FIGS. 5A and 5B  an on-chip core interconnect subsystem of a multi-core system (e.g., Tilera) includes a user dynamic network (UDN). The UDN provides a high performance on-chip mechanism to pass data between cores. In various embodiments, the UDN is used to implement the forwardCore( ) function of the LFM algorithm. 
     A transaction to send data from core C1 to core C2 follows the following procedure: Core C1 writes a data word to an egress UDN FIFO  502  on core C1 which is propagated down to the UDN switch of core C1. This operation may take about 2-3 cycles. Then the data word is propagated over the UDN to the ingress UDN FIFO  504  of the core C2. That may take one cycle per hop, i.e., the Manhattan distance between tile1  512  and tile2  514 , given by (|x1−x2|+|y1−y2|), where (x1, y1) are the row and column indices, respectively, of the tile1  512 , and (x2, y2) are the row and column indices, respectively, of the tile2  514 . An extra cycle may be required if the data needs to make a 90 degree turn, i.e., if the core C2 has neither a row index not a column index that is the same as that of the core C1. Next, the word propagates up from the UDN switch on to core C2. This operation may also take 2-3 cycles. 
     For example, if 16 cores are needed to implement a multi-core system, the maximum number of cycles required to transmit a word between two cores is: 3 (to get on the UDN switch)+3 (to traverse the UDN switch horizontally)+1 (to make a 90 degree turn)+3 (to traverse the UDN switch vertically)+3 (to get off the UDN switch)=13 cycles. In general, the time to forward data between two cores depends on their relative distance. Therefore, it may be important that cores participating in a single algorithm be strategically located so as to minimize the distance therebetween. Although an exemplary interconnect is described above using the Tilera multi-core system, it should be understood that various embodiments of a FIT can be based on other interconnect systems provided by the multi-core/processor systems for which that FIT embodiment is being tuned. 
     Various embodiments of FIT can provide the following benefits in comparison to the known approaches such as lock-based and atomic operation-based techniques. In the case of lock-based systems, the mechanism allowing concurrent access to the hash table without data corruption is a hardware lock, which is a memory-based lock. In the case of atomic operation-based algorithms, the mechanism is an atomic operation such as CAS, which also requires a memory-based lock. Various embodiments of FIT, however, make use of an on-chip hardware switch facility (e.g., UDN) to solve the concurrency problem, and thus, do not require a memory-based lock. 
     Division of labor: In embodiments of FIT, a bucket designated to a core is not processed by another core. As such a core in these embodiments need not access a remote cache of another core, as may be required in the lock and atomic-operation-based systems. Usually remote accesses to caches of other cores are slow compared to access to a core&#39;s own cache (e.g., in Tilera, 3 to 7 times slower than access to the local L2 cache). Therefore, various embodiments of FIT can be up to 3 to 7 times faster than other systems. 
     Cache hit ratio: In lock-based and CAS-based (i.e., atomic-operation-based) techniques, each core can potentially access any bucket of the hash table. Therefore, buckets will seek L2 and L1 local cache resources aggressively on each cache, causing several cache misses. As described above, a core in various embodiments of FIT need not access a remote cache of another core, and as a result these embodiments can yield a higher cache hit ratio compared to the other systems. 
     Zero memory-based lock: As described above, various embodiments of FIT do not use memory-based locks, and hence, unlike lock-based and atomic-operation-based systems, these embodiments do not cause a locking memory contention. Locking contentions can be a critical overhead in scaling up the number of cores. In various embodiments of FIT, memory-locking contentions are avoided, yet data corruption is also avoided by using an on-chip network, thus facilitating convenient scaling that may include a large number of processors/cores. 
     Memory access and inter-core data coherency: Consider the following situation in a traditional concurrent hash table. A core needs to modify a bucket that is currently hosted at a remote L2 cache. Such core needs first to load the remote bucket into its local cache and then modify it. Further, to ensure proper data coherency, the stale version of the bucket in the remote cache has to be updated. In various embodiments of FIT, there is no need to provide data coherency between L2 caches because these embodiments ensure that a bucket required by a core will either be in its local cache or, otherwise, in the main memory, but never in a remote cache. In some embodiments of FIT, if local cache operates at a high cache hit ratio, the need for data coherency between the local cache and main memory can be virtually avoided, substantially reducing the amount of memory accesses, thereby improving performance of the multi-core/processor system. 
     Smaller hash-table elements: In CAS-based (i.e., atomic-operation-based) algorithms, each element of the has table is required to have a CAS field, increasing the size of the element. In various embodiments of FIT, there is no need to keep any CAS field in the data element because synchronization is resolved via an on-chip network. Keeping the size of the element small can be important in order to maximize the number of elements that can fit into one bucket and therefore reduce the number of memory accesses required. 
     Memory access of atomic operations: Atomic operations such as CAS require at least one memory access, that are not required by various embodiments of FIT. 
     Separation of concerns: Various embodiments of FIT allow for a natural partition between workers (i.e., operations managing the hash table) and callers (i.e., the applications using the hash table). This can impact the performance of both the data and the instruction local caches. For instance, in various embodiments of FIT, the cores can be configured to exclusively run the LFM algorithm. For example, in Tilera, this is known as dataplane mode, or zero overhead on Linux. Because the LFM algorithm uses a relatively small number of instructions, the instructions of the algorithm may always found in the instruction cache, reducing the number of memory accesses. 
     Thus, it is seen that methods and systems for creating and/or operating fast interconnect tables that can improve system performance are provided. One skilled in the art will appreciate that the present invention can be practiced by other than the above-described embodiments, which are presented in this description for purposes of illustration and not of limitation. The specification and drawings are not intended to limit the exclusionary scope of this patent document. It is noted that various equivalents for the particular embodiments discussed in this description may practice the invention as well. That is, while the present invention has been described in conjunction with specific embodiments, it is evident that many alternatives, modifications, permutations and variations will become apparent to those of ordinary skill in the art in light of the foregoing description. Accordingly, it is intended that the present invention embrace all such alternatives, modifications and variations as fall within the scope of the appended claims. The fact that a product, process or method exhibits differences from one or more of the above-described exemplary embodiments does not mean that the product or process is outside the scope (literal scope and/or other legally-recognized scope) of the following claims.